JAVA-初步认识-第十三章-死锁示例
一.
接下来将的也是同步的一个小知识点,我们在使用同步的时候,会有这么一种现象,死锁。
什么情况下,是锁死?在我们程序当中,最常见的体现形式之一就是同步的嵌套。形象的说法是:两个人各有一只筷子,都想要吃饭,结果争执之下,谁都吃不了。和谐的情况就是,筷子给对方,对方吃饭之后,再连自己的筷子一起还回来,我们再吃饭。
和谐的情况有,相持不下的情况也有。这种相持的情况就是死锁,现在通过一个程序来验证一下。
死锁的一种体现形式之一,就是同步嵌套。
现在是同步函数中包含由同步代码块,同步代码块中包含着同步函数,同步函数的锁是this,同步代码块的锁是obj。
(这里我的疑问是两个同步代码块是同一个么?同步函数肯定是同一个)
流程是这样的,一个线程进来,先执行同步代码块,先拿obj锁,拿完锁就进来了。一进来又多了一个同步,这同步是同步函数,锁是this。这就是两锁,obj里面有个this。接着往下看,一个线程在读同步函数的时候,先拿this,this里面有谁,obj吧。这就是两个锁在嵌套。
接着就执行一下,
DOS结果显示直接卡在那儿了。再多次编译运行,还有全部交替输出的,那就是和谐的。
甚至还有直接挂掉的。
主线程睡10毫秒时,0线程就拿到了cpu执行权,当主线程醒了之后,就继续执行t.flag=false; t2.start();
当0线程得到执行权时,冲进来拿到同步代码块的obj锁,紧接着到show方法里拿this锁,然后读show函数,接着又进入同步代码块,读里面的内容,if里面的语句读了三句,100~98。紧跟着t2这个线程也要准备要读了,(它是按false进入的),是读else。这个0线程有可能出了object了,还没等出这show呢,t2线程就拿到了show所带有的this锁。它一拿到this锁,就进入show函数,而0线程拿着this,(也就是说0线程拿着在同步代码块的声明那,拿着obj想要进调用show函数的this,而1线程在show函数声明那,拿着this,想要进同步代码块拿obj),互相都不放,且都拿着自己的锁,谁都不放,谁都进不去,这种就是死锁。→我觉着这个争夺和执行权在谁手里有什么必要联系么?我是说,没有cpu执行权也能握有锁不放?
如果一个线程拿到锁,又出去了,全释放了。第二个线程接着进来,这就比较和谐了。
这是为了告诉大家,尽量不要设成死锁,这样问题不好解决。
二.
现在给大家介绍一个死锁程序,面试多线程的时候会碰到,请给我写个死锁程序。
写一个简单点的死锁程序。(遵循原则就一个嵌套)
标记是锁的意思么?
本例中两个嵌套的是同步代码块,(为什么不采用同步函数呢?),同时为这个两个同步代码块制备两个锁。
MyLock类中,对象locka前面的修饰符final是什么意思?
感觉上面的MyLock类中的定义挺奇怪的,到底是函数还是变量?由于是锁,肯定是函数,但是为什么这么写?
突然想到锁,或者同步,感觉逻辑很差,视频在讲解的时候,很多时候是自己构建了特点的环境。有没有对于同步更确切的描述呢?
以前说线程任务的时候,是一个对象(多个线程操作同一个任务),这里为什么new了两个线程任务呢?
两个线程执行路径,只能是两个任务,但是这并不影响我去演示,为什么呢?我们这两个线程运行的都是run方法,而这flag,虽然我这两个对象都有自己的flag,但是它们的值也是固定的,一个是true,另一个是false。
只有这种情况发生多个任务无所谓,因为你执行要么是true,要么是false,只有这两种情况。
我这线程任务里封装的资源是boolean型变量,虽然这个变量在两个任务对象当中都有独立的一份,但是取得值只能是两个,要么是真,要么是假。如果这里写的不是flag,而是num,int num=100,那就废了,这会导致两个线程任务执行的是两个100。
我们也可以不调用构造函数,那就要先给flag一个值,先满足一个值,然后再切换。
现在设想的这个程序能够锁上么?
从DOS结果看,就是锁住了,一个线程拿到了locka的锁,输出了“if locka.....”,但是没拿到lockb锁,因此进不来下一步。而另一个线程拿到了lockb锁,输出了“if lockb.....”,但是没有locka锁。最终的结果就是另个输出语句。
也可以将线程的名称输出,
DOS结果也显示的死锁。但是相同的这个程序换个cpu来执行,也许就和谐了。因此为了更大概率的出现我们需要展示的死锁线程,我们设置循环语句,执行的次数增加,自然出现死锁的概率就变大了。
前面书写的while(true),可能是一直循环,在后台打印时强制停止。
DOS结果显示,有锁死也有和谐,而且我们刚才说的while(true)可能就是意味着多次循环。