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();
                            }
                        }

      如何预防死锁问题:
        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 UnsafeThread {
                            //资源
                            private static int num=0;
                            //计算线程数量
                            private static CountDownLatch countDownLatch=new CountDownLatch(10);
                            private static ReentrantLock reentrantLock = new ReentrantLock();
    
                            //对资源进行操作
                            public static  void inCreate(){
    
                                //上锁
                                reentrantLock.lock();
                                num++;
                                reentrantLock.unlock();
    
    
                            }
                            
                            public static synchronized void inCreate(){
    
                                //上锁
                                
                                num++;
                                
    
    
                            }
                            
                            public static synchronized void inCreate(){
                                //上锁
                                synchronized(UnsafeThread.class){
                                    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();
                                //获取到当前计数器中的线程数量
                                /*while (true){
                                    if(countDownLatch.getCount()<=5){
                                        System.out.println(num);
                                        break;
                                    }
                                }*/
                                System.out.println(num);
    
    
                            }
                        }
  • 相关阅读:
    45到数据库查询题
    Error: Could not link: /usr/local/share/doc/homebrew
    根据两点坐标,计算连线与坐标轴间的夹角(弧度、角度)
    excel2json
    Mac下的unity兼容问题,打开项目提示错误:!GetPersistentManager().IsStreamLoaded(assetPath)
    Linker Command failed with exit code 1
    module.exports与exports区别
    Nginx配置SSL证书部署HTTPS方法
    Option path is not valid. Please refer to the README.
    javascript中call()、apply()、bind()的用法终于理解
  • 原文地址:https://www.cnblogs.com/ws1149939228/p/12518496.html
Copyright © 2011-2022 走看看