一、小结
1. 串行和并行
串行:一个线程在处理操作
并行:多个线程在处理同一个操作
2. 什么叫并发编程:再多线程环境下,应用程序的执行
3. 并发编程 的目的:充分运用到资源,提高程序的效率
4. 什么情况下用到并发编程 :
4.1 在线程阻塞时,导致应用程序停止
4.2 处理任务时间过长时2,可以创建子任务,来进行分段处理
4.3 见端倪任务执行
二、并发编程中待解决的问题
1. 并发编程中频繁上下文切换问题
频繁上下文切换,可能会带来一定的性能开销
如何减少上下文性能开销:
1.无锁编程
2.CAS:Compare and Swap,是比较并交换的意思
3. 使用最少线程数量
4. 协程:在单线程环境下进行多任务调度,而一再多任务之间进行交换
2. 并发编程中死锁问题
多个线程在抢占资源,但是抢占过程当中资源如果被占用,会造成阻塞,如果多个线程互抢资源时,就会造成死锁情况,死锁会导致应用程序的阻塞
编写测试代码
public class DeadLockTest { 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); } catch (InterruptedException e) { e.printStackTrace(); } //薅第二个人的头发 synchronized (HAIR_A){ System.out.println("第二个人薅到了的第一个人的头发"); } } }).start(); } }
控制台效果
命令窗口
如何防止死锁问题
1. 破坏请求和保持条件:在申请资源时,一次性将资源都申请到
2. 破坏不可占用资源:抢占资源如何不满足,那就释放所有资源,以如果在需要则再次申请即可
3. 破坏循环等待条件
3. 线程安全问题
多个线程同时操作同一个资源,可能会造成资源数据不安全问题
编写 示例代码
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(500); } catch (InterruptedException e) { e.printStackTrace(); } } //每一个 线程执行完毕,让计数减一 countDownLatch.countDown(); }).start(); } //等待计数器为0或者小0执行await下面代码 countDownLatch.await(); System.out.println(num); }
解决方案一:
private static int num=0; //计算线程数量 private static CountDownLatch countDownLatch=new CountDownLatch(10); //对资源进行操作 public static 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(500); } catch (InterruptedException e) { e.printStackTrace(); } } //每一个 线程执行完毕,让计数减一 countDownLatch.countDown(); }).start(); } //等待计数器为0或者小0执行await下面代码 countDownLatch.await(); System.out.println(num); }