zoukankan      html  css  js  c++  java
  • 并发编程介绍


     串行和并行:
                串行:一个线程在处理操作
                并行:多个线程在处理同一个操作

     什么叫做并发编程:

       在多线程环境下,应用程序的执行

     并发编程的目的:

         充分运用到资源,提高程序的效率

      什么情况下用到并发编程:
                1.在线程阻塞时,导致应用程序停止
                2.处理任务时间过长时,可以创建子任务,来进行分段处理
                3.间断任务执行
                
            
            一.并发编程中待解决的问题
                1.并发编程中频繁上下文切换的问题
                    频繁上下文切换,可能会带来一定的性能开销
                    如何减少上下文性能开销:
                        1.无锁并发编程
                        2.CAS
                        3.使用最少线程数量
                        4.协程:在单线程环境下进行多任务的调度,可以在多任务之间进行任务切换
                
                
                2.并发编程中死锁问题
                    多个线程在抢占资源,但是抢占过程当中资源如果被占用,会造成阻塞,如果多个线程互抢资源时,就会造成死锁情况,死锁会导致应用程序的阻塞
                    
                    案例:    

                        public class DeadLockDemo {
                            //资源
                            private static final Object HAIR_A=new Object();
                            private static final Object HAIR_B=new Object();
    
                            public static void main(String[] args) {
                                //第一个人
                                new Thread(()->{
                                    //护住自己的头发
                                    synchronized (HAIR_A){
                                        System.out.println("第一个人护住自己的头发,准备薅第二个人的头发");
                                        //延迟时间
                                        try {
                                            Thread.sleep(100);
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                        //薅第二个人的头发
                                        synchronized (HAIR_B){
                                            System.out.println("第一个人薅到了第二个人的头发");
                                        }
                                    }
                                }).start();
    
    
                                //第二个人
                                new Thread(()->{
                                    //护住自己的头发
                                    synchronized (HAIR_B){
                                        System.out.println("第二个人护住自己的头发,准备薅第一个人的头发");
                                        //延迟时间
                                        try {
                                            Thread.sleep(100);      //当前线程休眠,让渡CPU资源
                                        } catch (InterruptedException e) {
                                            e.printStackTrace();
                                        }
                                        //薅第一个人的头发
                                        synchronized (HAIR_A){
                                            System.out.println("第二个人薅到了第一个人的头发");
                                        }
                                    }
                                }).start();
                            }
                        }

     jconsole查看死锁详细信息

     


                    如何预防死锁问题:
                        1.破坏请求和保持条件:在申请资源时,一次性将资源都申请到 (尽量在同一个代码块请求资源)
                        2.破坏不可占用条件:抢占资源如何不满足,那就释放所有资源,以后如果再需要则再次申请即可(不一直占用资源,没有申请到资源就先释放再申请)
                        3.破坏循环等待条件(指定执行顺序)
                        
                3.线程安全问题
                    多个线程同时操作同一个资源,可能会造成资源数据不安全问题
                    
                    示例:
                      

                public class UnsafeThread {
                            //资源
                            private static int num=0;
                            //计算线程数量
                            private static CountDownLatch countDownLatch=new CountDownLatch(10);
                            //对资源进行操作
                            public static void inCreate(){
                                num++;
                            }
    
    
                            public static void main(String[] args) throws InterruptedException {
                                for (int i = 0 ; i < 10 ; i++ ){
                                    new Thread(()->{
                                        for (int j = 0 ; j < 100; j++){
                                            inCreate();
                                            try {
                                                Thread.sleep(100);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                        //每一个线程执行完毕,让计数-1
                                        countDownLatch.countDown();
                                    }).start();
                                }
                                //等待计数器为0或者小于0执行await下面代码
                                countDownLatch.await();
                                System.out.println(num);
                            }
                        }

    多次执行效果都不一致,都与预期值不符

     


                    解决线程不安全问题:

    public class SafeThread {
            //资源
            private static int num=0;
            //计算线程数量
            private static CountDownLatch countDownLatch=new CountDownLatch(10);
            private static ReentrantLock reentrantLock = new ReentrantLock();
    
            //对资源进行操作
            public static synchronized void inCreate(){
                //上锁
                num++;
            }
            
            /*public static synchronized void inCreate(){
                //上锁
                synchronized(SafeThread.class){
                    num++;
                }
            }*/
    
            /*public static void inCreate(){
                //上锁
                reentrantLock.lock();
                num++;
                reentrantLock.unlock();
            }*/
    
    
            public static void main(String[] args) throws InterruptedException {
                for (int i = 0 ; i < 10 ; i++ ){
                    new Thread(()->{
                        for (int j = 0 ; j < 100; j++){
                            inCreate();
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        //每一个线程执行完毕,让计数-1
                        countDownLatch.countDown();
                    }).start();
    
                }
                //等待计数器为0或者小于0执行await下面代码
                countDownLatch.await();
                //获取到当前计数器中的线程数量
                                /*while (true){
                                    if(countDownLatch.getCount()<=5){
                                        System.out.println(num);
                                        break;
                                    }
                                }*/
                System.out.println(num);
    
    
            }
    
    }

    得到预期值

  • 相关阅读:
    处理接口返回script标签对
    跨域问题总结
    CordMirror 在线代码编辑器
    解决IOS移动端 new Date 为 Invalid Date bug
    大屏数据可视化
    Xcode清理缓存
    ArrayMap和HashMap区别
    javacript总结
    css总结
    html总结
  • 原文地址:https://www.cnblogs.com/chx9832/p/12518613.html
Copyright © 2011-2022 走看看