美文网首页
《JAVA并发编程的艺术》要点(一)并发编程的挑战

《JAVA并发编程的艺术》要点(一)并发编程的挑战

作者: YongtaoHuang | 来源:发表于2019-07-26 10:57 被阅读0次

    并发编程的目的是为了让程序运行的更快

    并发编程面临的挑战

    一、上下文切换问题
    二、死锁问题
    三、资源受限问题

    (一)上下文切换

    CPU通过给每个线程分配CPU时间片(几十毫秒)来实现多线程。
    CPU通过时间片分配算法来循环执行任务。任务从保存到再加载的过程就是一次上下文切换。但是,多线程不一定快,测试代码如下:

    /**
     * 并发和单线程执行测试
     */
    public class ConcurrencyTest {
    
        /** 执行次数 */
        private static final long count = 100000000l;
    
        public static void main(String[] args) throws InterruptedException {
            //并发计算
            concurrency();
            //单线程计算
            serial();
        }
    
        private static void concurrency() throws InterruptedException {
            long start = System.currentTimeMillis();
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int a = 0;
                    for (long i = 0; i < count; i++) {
                        a += 5;
                    }
                }
            });
            thread.start();
            int b = 0;
            for (long i = 0; i < count; i++) {
                b--;
            }
            thread.join();
            long time = System.currentTimeMillis() - start;
            System.out.println("concurrency :" + time + "ms");
        }
    
        private static void serial() {
            long start = System.currentTimeMillis();
            int a = 0;
            for (long i = 0; i < count; i++) {
                a += 5;
            }
            int b = 0;
            for (long i = 0; i < count; i++) {
                b--;
            }
            long time = System.currentTimeMillis() - start;
            System.out.println("serial:" + time + "ms" );
        }
    
    }
    

    当count = 100000000l时,输出结果:

    concurrency :48ms
    serial:74ms
    

    当count = 10000l;时,输出结果:

    concurrency :1ms
    serial:0ms
    

    从上述试验结果可知:多线程不一定快,使用多线程得在合适的场合。
    如何减少上下文切换:
    1、无锁并发编程
    2、CAS算法(比较并交换)
    3、使用最少线程
    4、协程

    (二)死锁

    在多任务系统下,当一个或多个进程等待系统资源,而资源又被进程本身或其它进程占用时,就形成了死锁。死锁会造成系统功能不可用。下面举一个典型的例子来说明死锁问题:

    /**
     * 死锁例子
     */
    public class DeadLockDemo {
    
        /** A锁 */
        private static String A = "A";
        /** B锁 */
        private static String B = "B";
    
        public static void main(String[] args) {
            new DeadLockDemo().deadLock();
        }
    
        private void deadLock() {
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (A) {
                        try {
                            System.out.println("线程t1获得A锁,准备去拿B锁");
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        synchronized (B) {
                            System.out.println("线程t1获得B锁");
                        }
                    }
                }
            });
    
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (B) {
                        System.out.println("线程t2获得B锁,准备去拿A锁");
                        synchronized (A) {
                            System.out.println("线程t2获得A锁");
                        }
                    }
                }
            });
            t1.start();
            t2.start();
        }
    
    }
    

    输出结果:

    线程t1获得A锁,准备去拿B锁
    线程t2获得B锁,准备去拿A锁
    

    避免死锁的几个方法:
    1、避免一个线程同时获得多个锁
    2、尽量每个锁占用一个资源
    3、用定时锁替代内部锁机制
    4、对于数据库锁,加解锁必须在一个数据库连接里,否则会解锁失败

    (三)资源受限

    资源限制是指在并发编程时,程序的执行速度受限于软硬件资源。
    将某段串行代码并发执行,因为资源受限,代码实际上并发度不高,反而增加了上下文切换和资源调度的时间。

    硬件资源

    带宽的上传下载,硬盘读写速度,CPU的处境速度等
    解决方法:服务器集群

    软件资源

    数据库连接数,socket连接数等
    解决方法:使用资源池将资源复用

    根据不同的资源限制调整程序的并发度

    相关文章

      网友评论

          本文标题:《JAVA并发编程的艺术》要点(一)并发编程的挑战

          本文链接:https://www.haomeiwen.com/subject/xoclrctx.html