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);
    
    
                            }
                        }
    复制代码
  • 相关阅读:
    java 虚拟机启动参数[转]
    Android SDK Manager 无法下载更新,或者更新速度超慢,或者待安装包列表不显示
    fluentnhibernet auto mapping
    取消sqlserver 锁表
    TFS 2010 配置的时候,提示TF255466错误
    doc中文乱码的解决方法 中英文切换
    silverlight 读取wcf服务 读取宿主端的config 良好的方法
    dojo+js+html5学习网址
    win 7 64位 配置silverlight 32位的应用程序(sl网站)
    HTTP协议及其POST与GET操作差异 & C#中如何使用POST、GET等
  • 原文地址:https://www.cnblogs.com/tinghao/p/12520559.html
Copyright © 2011-2022 走看看