扫码关注公众号
产生死锁的条件
1.互斥条件:一个资源每次只能被一个进程使用。2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。3.不剥夺条件:进程已
悲观锁和乐观锁有什么区别?
悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。正因为如此,悲观锁需要耗费较多的时间,另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。说到这里,由悲观锁涉及到的另外两个锁概念就出来了,它们就是共享锁与排它锁。共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。乐观锁:是用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的version字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加1。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。比如:1、数据库表三个字段,分别是id、value、versionselectid,value,versionfromtwhereid=#{id}2、每次更新表中的value字段时,为了防止发生冲突,需要这样操作updatetsetvalue=2,version=version+1whereid=#{id}andversion=#{version}
什么是线程死锁?
线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。
死锁是如何产生的?
#场景一星期日早上十点半,你在公路上开车,这是一条窄路,只能容纳一辆车。这时,迎面又驶来一辆车,你们都走到一半,谁也不想倒回去,于是各不相让,陷入无尽的等待。#场景二你和她吵架了,谁也不理谁,甚至晚饭时间都各自煮饭。你在炒京酱肉丝,她在做葱烤鲫鱼。炒到一半你发现小葱被她全部拿走了,于是你默默等待她做好菜后再去拿,殊不知她也在等待你炒完菜后来拿酱油。#场景三你和四个好朋友坐在圆形餐桌旁,你们只做两件事情:吃饭,或者思考。吃饭的时候,你们就停止思考。思考的时候,也停止吃饭。每个人面前有一碗兰州拉面,并且每个人左右两边各有一根筷子。你们必须要拿到两根筷子才能开始吃面。吃完后再放下筷子,让别人可以使用。吃了一会之后,每个人都拿起了自己左手边的筷子,导致每个人都只有一根筷子,并且等待别人吃完放下筷子给自己。可惜,没有人吃到面,所以没有人会放下筷子。(著名的哲学家就餐问题)#场景四你有两个线程A和B,各自在加锁的状态下运行。A持有一部分资源,并且等待B线程中的资源以完成自己的工作,而此时B线程也在等待A中的资源以完成自己的工作。由于他们都是锁定状态,所以他们必须完成了自己的工作后,自己持有的资源才能释放。于是线程无休止地等待,导致死锁。代码如下publicclassJavaTest{@Testpublicvoidtest(){finalObjectlockA=newObject();finalObjectlockB=newObject();newThread(newRunnable(){@Overridepublicvoidrun(){synchronized(lockA){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}synchronized(lockB){}System.out.println("finishA");}}}).start();newThread(newRunnable(){@Overridepublicvoidrun(){synchronized(lockB){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}synchronized(lockA){}System.out.println("finishB");}}}).start();try{Thread.sleep(10000);}catch(InterruptedExceptione){e.printStackTrace();}}}此程序中,线程A持有lockA对象,并请求lockB对象;线程B持有lockB对象,并请求lockA对象。由于他们都在等待对方释放资源,所以会产生死锁。运行程序,将发现控制台无法打印出"finishA"和"finishB"消息。这些都是程序员在工作或生活中会遇到的问题,人生就像是一个进程,时间是我们的主线程,期间做的每一件事都是开启的一个子线程。当多件事冲突时,并发问题就产生了。这就是死锁的产生。