00:00
那么接下来咱们继续往下看,各位啊,再往下的话,咱们干嘛呢?诶咱们来看看啊,锁这种东西啊,一旦用不好会出现死锁吗。会不会出现死锁的现象?死锁听这个名儿就挺的是吧,叫死锁。怎么就发生死锁现象了呢?就你一不小心,程序员写着写着把自己锁死了。锁死了。对,你比如这有个对象。这儿有一个对象。是吧,你有两个线,你有两个线程,T1线程,这是什么呀?叫T2线程。T线程的,你是从上往下执行,你是这种节奏。T一线呢?TT2线程你是从下往上执行,是这个节奏,你的顺序不一样,假如T1线程呢,它要锁住这个对象,同时它要干什么呀,锁住这个对象。有没有可能,T2是先锁这个对象。
01:02
然后呢,再去锁这个对象。有没有这个可能?有这个可能吗?假如说T一线能把这个对象锁住了,然后怎么着啊,它这个代码怎么着。再往下锁,这个的时候锁不了。这个对象呢,被T2线程锁了。T2000往下走,锁这个对象的时候锁不了。对吧,为什么,因为这个对象已经被这个T1锁了。你看啊,你好好理解理解死锁现象,死锁会让程序啊。停到哪儿?而且不出任何异常,也不出任何错误。来。对,33。啊,死锁。
02:01
不出异常也不出错误啊,是非常诡异的。不出现异常,也不会出现错误。程序一直僵持在那里。这种错误最难调试。这种错误是最难调试的。没事儿,我一会儿给你写一下代码,你就理解了。就是T线程在执行过程当中啊,他去锁这个对象,然后再去锁这个对象,它只有这两两个锁都锁住之后,他可能这把这个代码才执行结束。这个代码执行结束,他可能才会把这两个对象锁都释放掉,如果T2也是这样的话,假如说T1锁住一个,恰好T2呢把这个锁住了,T1呢,锁住这个之后呢,它不会放手,为什么?因为代码没有执行结束,他继续锁第二个锁不上,为什么?因为这个对象被T2锁了,T2现在锁住一个之后呢,T2继续往下锁,锁这个对象,这个对象他也锁不住,为什么这个对象T1被占,被T1锁锁锁住这个对象了,所以这个时候呢,就会僵持住。
03:10
僵持住。啊,僵持住,我们可以写个代码来看一看,好吧,来建一个package,各位。呃。好奇怎么实现是吧,来看看啊,我们叫deadlock。Deadlock,死锁死锁啊死锁呢,有的时候面试官让你写。叫deadlock啊,Deadlock来死锁代码要会写,死锁代码要会写啊,一般面试官要求你会写啊,你会写,只有会写的才会意,才会在以后的开发中注意这个事儿。
04:01
明白吧,只有会写的才会在以后开发中注意这个事儿。啊,因为死锁很难调试,很难调试啊来我们看一下,假如说现在呢,我们有一个线程,我就这样写的,各位啊,有个线程叫my thread,一去继承这个thread。好了,这是一个线程,然后呢,这里有一个线程叫my thread02呢,去my thread2啊去继承什么呀,我们的一个thread,然后呢,继承之后呢,接下来在这呢,有一个什么叫object o1,然后有个object o2,然后接下来在这里有个构造方法,大家注意听课啊,注意听课来这是构造方法,有一个object什么呀,O1,然后有object什么呀,O2,然后这写着我们那个ZO1。ZOE等于O1 Z o2呢等于O2,好,这是很普通的代码,然后这里呢,我们有个方法叫做run方法,Run啊run好了,那么接下来把这个代码原封不动拷贝到这个地方,然后呢,把这个类名改一下就行了,别的地方不动。
05:05
就两个T1 T2,两个线程共享O1和O2。O1和O2啊,然后接下来我这地方啊,我对象六的时候object o1呢,一个object就行了,然后接下来我们继续往下object object or等于new一个object好出来,然后接下来这个对象丢了,这个对象了完之后呢,接下来线程看好了啊,叫做THREAD1这个线程thread t线程等于new一个什么呀,My thread。把O1和O二传进去,那么的T2的new一个MYTH2,然后呢,把O1和O二传进去,好大家注意听啊,O1扭出来,O2扭出来,把它传进去,这样的话是不是代表T1和T2 t1和T22个线程共享O1O2。因为这扭了一次啊,这也扭了一次啊,O1O2O1O2是不是传进去了,哎,那T1线程start启动,T2线程start启动,好,那么接下来我们来看看这个run方法怎么写,它就会能锁住个位。
06:09
注意听啊,注意听来看你比如说这个run方法,我先把谁锁住O1,锁住O1之后,我紧接着再去锁谁O2,然后把这个代码复制一份放到这个位置上,我们把这个位置改成O2,这个位置改成O1。这就是死锁。因为大家都知道这个这是嵌套了,对不对,这个大括号里面代码执行结束。是不是才能释放的锁?这个大块代码执行结束是不是才能释放OE的错误?O1的锁占住之后去执行这个代码,这个代码去锁O2吗?锁O2的时候对不起,这块已经怎么着,这个方法在执行的时候把O2锁住了。
07:07
把O2锁住之后呢,紧接着他去锁O1,锁O1呢锁不了。锁OE锁不了,原因是因为上面把OE锁了,我问大家问题啊,这个程序有没有可能执行很正常?有没有可能执行很正常?有没有可能执行很正常?就这个程序有没有可能执行很正常。嗯。有没有可能说一个线程把O1锁了,O2锁了之后,诶执行结束,O1和O2的锁怎么着。都释放了,紧接着另外一个线程才开始执行,是不是就没事儿?对吧,什么时候它必然会出问题。让锁住欧一这睡一会儿。对吧,让他锁住O2的时候在这怎么着睡一会儿,大家想想是不是就一定会出问题?对吧,哎,你想想啊,来睡会儿吧,点sleep对吧,睡一秒。
08:02
来,我们把这个方法加上去。全开始来,把这个代码拿过来,这睡一秒,然后这也睡一秒,大家想这这就完蛋了,这就完犊子了,你O1锁住之后睡了。然后呢,这个程序O2锁住之后这睡了。是吧,所以这个O1这边就锁不了了,那么等他醒来一秒之后,锁O1锁不上,等他醒来之后锁O2锁不上,僵持住了,我们来看这个代码。这个代码呢,就是这样,一年之后还是这样。两年之后还是这样,三年之后还是这样,十年之后还是这样。注意啊,这个程序啊,就不要随便不要不要随便来,不要随便写啊就synchronized在开发中最好不要嵌套使用synchronized啊,在开发中最好不要嵌套使用。啊,一不小心就可能会导致死锁现象的发生。
09:02
啊,发生之后呢,就比较尴尬啊,比较尴尬,因为这个程序到底在哪错了,你不知道啊,你不知道,所以这块呢,给大家说一下,有这么一个死锁的一个情况好吧,哎,死锁的情况啊。强行终止了啊,强行终止stop。
我来说两句