zoukankan      html  css  js  c++  java
  • (二)并发编程的优缺点

    1.并发编程的优点:

            面对复杂业务模型,并行程序比串行程序更适应业务需求,而并发编程更吻合这种业务拆分,正是因为这些优点,使得多线程技术能够得到重视,也是一名CS学习者应该啊掌握的;

    • 充分利用多喝CPU的计算能力
    • 方便进行业务拆分,提升应用性能

    2.并发编程的缺点:

           多线程技术有这么多的好处,难道就没有一点缺点,就在任何场景下就一定适用么?很显然不是

    2.1频繁的上下文切换

           时间片是CPU分配给各个线程时间,因为时间非常短,所以CPU不断通过切换线程,让我们觉得多个线程是同时执行的,时间片一般是几十毫秒.而每次切换时,都要保存当前的状态,以便能够恢复先前状态,而这个切换是非常损耗性能的,过于频繁反而无法发挥多线程编程的优势.通常减少上下文切换可以采用无锁并发编程,CAS算法,使用最小的线程和使用协程.

    • 无锁并发编程:可以参照concurrentHashMap锁分段的思想,不同的线程处理不同段的数据,这样在多线程竞争的条件下,可以减少上下文切换.
    • CAS算法:利用Atomic下使用CAS算法来更新数据,使用了乐观锁,可以有效的减少一部分不必要的锁竞争带来的上下文切换.
    • 使用最少线程:避免创建不需要的线程,比如任务很少,但是创建了很多的线程,这样会造成大量的线程都处于等待状态.
    • 协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换.

    2.2线程安全

          多线程编程中最难把握的就是临界区线程安全问题,稍微不注意就会出现死锁的情况出现,一旦产生死锁就会造成系统功能不可用.

    public class DeadLockDemo {
        private static String resource_a = "A";
        private static String resource_b = "B";
    
        public static void main(String[] args) {
            deadLock();
        }
    
        private static void deadLock() {
            Thread threadA = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (resource_a) {
                        System.out.println("get resource a");
                        try {
                            Thread.sleep(3000);
                            synchronized (resource_b) {
                                System.out.println("get resource b");
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            Thread threadB = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (resource_b) {
                        System.out.println("get resource b");
                        synchronized (resource_a) {
                            System.out.println("get resource a");
                        }
                    }
                }
            });
            threadA.start();
            threadA.start();
        }
    
    }

    那么,通常可以用如下方式避免死锁的情况

    1. 避免一个线程同时获得多个锁.
    2. 避免一个线程在锁内部占有多个资源,尽量保证每个锁只占有一个资源.
    3. 尝试使用定时锁,使用lock.tryLock(timeOut),当超时等待时,当前线程不会阻塞.
    4. 对于数据锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况.

    所以,如何正确的使用多线程编程技术有很大的学问,比如如何保证线程安全,如何正确理解由于JMM内存模型在原子性,有序性,可见性带来的问题,比如数据脏读,DCL等这些问题(在后续篇幅会讲述).在学习多线程编程技术的过程中会让你收获颇丰.所以要重视多线程编程.

  • 相关阅读:
    【洛谷P2860】冗余路径
    【CF1042D】Petya and Array 离散化+树状数组
    【洛谷P2127】序列排序
    【洛谷P4462】异或序列
    【SPOJ10707】COT2
    【CF1119D】Frets On Fire
    【CF1119E】Pavel and Triangles
    【洛谷P1903】数颜色
    hdu 3488(KM算法||最小费用最大流)
    hdu 1853(拆点判环+费用流)
  • 原文地址:https://www.cnblogs.com/pingping-joe/p/9186930.html
Copyright © 2011-2022 走看看