多线程学习二之线程之间实现同步
上篇博客回顾:
1.线程与进程区别:进程是所有线程的集合,线程是进程中的一条执行路径
2.为什么要使用多线程:提高程序效率
3.多线程应用场景:提高程序运行效率,比如迅雷 分批处理数据
4.多线程创建方式:三种创建方式 继承Thread 、实现Runnable接口、匿名内部类
5.获取线程对象以及名称:查看Api
6.线程运行状态:新建状态、运行状态、就绪状态、阻塞状态、死亡状态
这篇博客记录线程之间实现同步学习记录
线程安全
synchronized用法
死锁
一、先看看什么是线程安全
1.为什么有线程安全问题 什么时候出现线程安全问题?
我们先来看下案例:
运行结果:
线程一和线程二同时抢口香糖时会重复出售
结论:当多个线程同时共享同一个全局变量或静态变量,做写的操作时可能会发生数据冲突问题也就是线程安全问题。但是做读操作是不会发生数据冲突问题。
二、线程安全解决方案
1.使用同步代码块
将可能会发生线程安全问题的代码,给包括起来。
synchronized(同一个数据){
可能会发生线程冲突问题
}
案列
2.同步函数
在方法上修饰synchronized称为同步函数 值得注意的是同步函数使用的是this锁
案列:
3.静态同步函数
方法上加上static关键字,使用synchronized 关键字修饰。
静态的同步函数使用的锁是当前类名.class
4.使用锁(lock)
在 jdk1.5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,Lock 接口提供了与 synchronized 关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。
三、synchronized和lock比较
Lock 接口可以尝试非阻塞地获取锁当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
*Lock 接口能被中断地获取锁与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。
Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。
四、多线程死锁
案列:
输出结果:
思考
1.flag为true时,先拿到obj锁再拿到this锁,才执行代码
2.flag为false时,先拿到this锁再拿到obj锁,才执行代码
3.两个线程同时执行时flag为true线程去拿flag为false的obj锁是会产生死锁
结论 :导致多线程死锁的原因是同步中嵌套同步,导致锁无法释放