并发编程

串行和并行:

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


                        }
                    }
原文地址:https://www.cnblogs.com/ws1149939228/p/12518496.html