并发编程

并发编程专题内容:
  串行和并行:
   串行:一个线程在处理操作
   并行:多个线程在处理同一个操作
  什么叫做并发编程:在多线程环境下,应用程序的执行
  并发编程的目的:充分运用到资源,提高程序的效率
  什么情况下用到并发编程:
   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);

      }
     }
posted @ 2020-03-18 18:21  林染plus  阅读(116)  评论(0编辑  收藏  举报