打印结果:
线程1获取到锁1线程2获取到锁2
然而程序并没有停止,两个线程都进入了阻塞状态,等待对方先释放锁
锁死
等待线程由于唤醒其所需的条件永远无法成立,或者其他线程无法唤醒该线程,导致该线程一直处于等待状态,这种情况就是锁死
public static void main(String[] args) {Object object = new Object();new Thread(()->{try {TimeUnit.SECONDS.sleep(1);synchronized (object){System.out.println("开始等待");object.wait();}}catch (InterruptedException e) {e.printStackTrace();}}).start();new Thread(()->{synchronized (object){System.out.println("开始唤醒");object.notifyAll();}}).start();}
打印如下:
开始唤醒开始等待
比如这种情况,因为先发生唤醒,后进行等待,导致的无限等待情况,就属于锁死中的信号丢失锁死
第二种锁死则是嵌套监视器锁死
这种锁死和上面死锁的演示代码有些相似
public static void main(String[] args) throws InterruptedException {Object monitorA = new Object();Object monitorB = new Object();new Thread(()->{synchronized (monitorA){synchronized (monitorB){try {System.out.println(Thread.currentThread().getName()+"进入等待");monitorB.wait();} catch (InterruptedException e) {e.printStackTrace();}}}},"线程01").start();TimeUnit.SECONDS.sleep(1);new Thread(()->{synchronized (monitorA){synchronized (monitorB){System.out.println(Thread.currentThread().getName()+"开始唤醒");monitorB.notifyAll();}}},"线程02").start();}
打印结果:
线程01进入等待
程序依然没有执行,因为虽然线程01释放了的锁,但是并没有释放的锁,而即使空闲了,但是线程02不能进入引导的临界区,更无法去唤醒线程01,导致了锁死的发生
线程饥饿
线程饥饿是指线程一直无法获得必须的资源,而导致不能继续运行下去的一种活性故障 。如何把锁看做是一个资源的话,死锁也是一种线程饥饿 。但线程饥饿并不会导致死锁
活锁
活锁是指线程一直处于运行状态,但是它的任务并没有进展,就像是小猫咬自己的尾巴,虽然一直追着咬,但是始终咬不到 。
线程饥饿可能演变成活锁
对象发布和初始化的安全问题 对象发布
对象发布是指对象在作用域外被其他线程所使用 。
有这几种发布形式:
将对象引用存储在变量中在非方法中返回一个对象使用内部类,让当前对象在内部类中使用通过方法调用将对象传递给外部方法 对象逸出
同样,与之对应的是对象逸出,即一个对象的发布出现了我们不期望的结果或者对象发布本身不是我们所期望的
有这两种情况:
方法返回一个对象还未完成初始化,就将对象传递给外界:
this赋值:
比如这么一个类:
class Escpae{private Map
本来是设定为只读的,但是又有一个方法,能够获取到对象,这就导致的对象的逸出,我们可以在外部对它进行修改
public static void main(String[] args) {Escpae escpae = new Escpae();Map cities = escpae.getCities();System.out.println(cities.remove(3));System.out.println(cities.get(3));}
执行之后,再次获取就返回null
- 设计好的API
- Neo4j和Cypher快速入门
- 终极一班2百度云 终极一班2百度云资源
- QT窗体绘图QPainter
- 【go】go 实现行专列 将集合进行转列
- 教学先进个人与教坛新秀证书一样吗 教学先进个人评职称有用吗
- 一 HTML5基础:HTML 基础+格式化文本与段落
- 逐步改善,设计优秀的API
- 逐步改善,设计优秀API
- 去以六月息者也上一句 去以六月息者也的以翻译