扁平式的网站,ai建站工具,正规考证培训机构,靖江网站制作多少钱用幽默浅显的言语来说死锁 半生#xff1a;我已经拿到了机考的第一名#xff0c;就差笔试第一名了 小一#xff1a;我已经拿到了笔试的第一名#xff0c;就差机考第一名了 面试官#xff1a;我很看好你俩#xff0c;继续干, 同时拿到2个的第一名才能拿到offe… 用幽默浅显的言语来说死锁 半生我已经拿到了机考的第一名就差笔试第一名了 小一我已经拿到了笔试的第一名就差机考第一名了 面试官我很看好你俩继续干, 同时拿到2个的第一名才能拿到offer进入我XX大厂 半生小一你的笔试第一名让我可好 小一做梦我还要你的机考第一名呢 半生就你那水平zz 小一WTF来干一架 半生来呀who怕who 于是死锁产生了狭路相逢勇者胜电脑死机了。 什么是死锁死锁的产生条件是什么 1.死锁是指两个或多个线程互相等待对方释放所持有的资源从而导致进程无法继续执行的一种情况。具体来说死锁发生时线程会进入一个永久等待的状态无法继续执行并最终导致程序无响应或崩溃。
2.产生死锁的条件通常被称为死锁的四个必要条件包括
互斥条件Mutual Exclusion至少有一个资源被多个线程独占也就是说一个资源同时只能被一个线程占用。请求与保持条件Hold and Wait线程已经持有了至少一个资源并且在等待获取其他线程占有的资源。不可剥夺条件No Preemption已经获得的资源不能被其他线程抢占只能由占有它的线程显示地释放。循环等待条件Circular Wait多个线程形成一个循环等待的等待链即每个线程都在等待下一个线程所持有的资源。
只有当上述四个条件同时满足时死锁才可能发生。 下面上一段代码有问题的代码考考你们的眼力跟基本功 public static void main(String[] args) {final Object resource1 new Object();final Object resource2 new Object();Thread thread1 new Thread(() - {synchronized (resource1) {System.out.println(Thread 1:锁住offer1);}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource2) {System.out.println(Thread 1:锁住offer2);}});Thread thread2 new Thread(() - {synchronized (resource2) {System.out.println(Thread 2:锁住offer2);}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource1) {System.out.println(Thread 2:锁住offer1);}});thread1.start();thread2.start();} 为什么这2个线程都锁不住这个offer 肥水不流外人田既然你们都锁不住这个offer就让我来~ public static void main(String[] args) {final Object resource1 new Object();final Object resource2 new Object();Thread thread1 new Thread(() - {synchronized (resource1) {System.out.println(半生:锁住了机考第一名);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource2) {System.out.println(半生:笔试第一名);}}});Thread thread2 new Thread(() - {synchronized (resource2) {System.out.println(小一:锁住了笔试第一名);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource1) {System.out.println(小一:锁住机考第一名);}}});thread1.start();thread2.start();}又是你俩干啥呢死锁了呀~offer不止一个呀就不能友好相处快乐的玩耍同时都拿到offer么 让我来looklook一下字节码指令是怎么去执行的 1. 先使用javac -encoding UTF-8 X.java 来生成class文件
2. javap -verbose X.class 反编译 3.从反编译的指令来看这里应该是操作系统或者jvm虚拟机检查到了这是个死锁强制中断了在使用synchronized作为锁的时候我们知道是有monitorenter monitorexit 这一对指令的但是这里就没有看到
4. 下载了个idea的插件jclasslib 来查看看字节码指令是否一致 5.可以看到这里是有这一对锁指令的这里稍微解释下上写字节码指令的含义
0 aload_0加载索引为0的引用到操作数栈通常用于加载实例方法的隐式参数即this。1 dup复制栈顶的元素并将复制后的值重新压入栈顶。2 astore_2将栈顶的引用类型数值存储到局部变量表的索引为2的位置。3 monitorenter进入同步块前获取锁。4 getstatic #3 java/lang/System.out : Ljava/io/PrintStream;获取静态字段System.out的值即标准输出流PrintStream对象。7 ldc #12 小一:锁住了笔试第一名将常量池中索引为12的String类型常量加载到操作数栈。9 invokevirtual #5 java/io/PrintStream.println : (Ljava/lang/String;)V执行PrintStream对象的println方法其中参数为栈顶的String类型常量。12 ldc2_w #13 1000将常量池中索引为13的long类型常量加载到操作数栈。15 invokestatic #15 java/lang/Thread.sleep : (J)V执行Thread类的静态方法sleep其中参数为栈顶的long类型常量。18 goto 33 (15)无条件跳转到字节码指令33即跳过下方的指令。21 astore_3将栈顶的引用类型数值存储到局部变量表的索引为3的位置。22 getstatic #3 java/lang/System.out : Ljava/io/PrintStream;获取静态字段System.out的值。25 ldc #17 小一:被中断释放笔试资源将常量池中索引为17的String类型常量加载到操作数栈。27 invokevirtual #5 java/io/PrintStream.println : (Ljava/lang/String;)V执行PrintStream对象的println方法其中参数为栈顶的String类型常量。30 aload_2加载局部变量表中索引为2的引用类型数值到操作数栈。31 monitorexit退出同步块释放锁。32 return返回void类型的值并结束当前方法。33 aload_1加载局部变量表中索引为1的引用类型数值到操作数栈。34 dup复制栈顶的元素并将复制后的值重新压入栈顶。35 astore_3将栈顶的引用类型数值存储到局部变量表的索引为3的位置。
这里的指令
第9 invokevirtual #5 java/io/PrintStream.println : (Ljava/lang/String;)V执行PrintStream对象的println方法其中参数为栈顶的String类型常量。执行了catch中的打印日志说明被执行中断了后面goto 33 跳到33行的指令 6.此外我另外写了同步方法来看看 从这里看出它是有加锁的第20行多了一个monitorexit这就是防止异常强制释放锁也就是synchronized能自动释放锁的保障 于是解决死锁的方式来了~ 退一步想阔天空你好我好大家好
public static void main(String[] args) {final Object resource1 new Object();final Object resource2 new Object();Thread thread1 new Thread(() - {synchronized (resource1) {System.out.println(半生:获得了机考第一名);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource2) {System.out.println(半生:获得了笔试第一名);}}});Thread thread2 new Thread(() - {synchronized (resource1) {System.out.println(小一:获得了笔试第一名);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (resource2) {System.out.println(小一:获得了机考第一名);}}});thread1.start();thread2.start();} 只要稍微改下获取资源的顺序半生跟小一就分别都获取了机考笔试第一名都收到了XX大厂offer
打破死锁的方式有多种只要四个死锁的必要条件去其一就可以了 常用的有以下几种常见的方式可以用来解决死锁问题 避免循环等待通过对资源加锁的顺序进行规定以避免线程之间互相等待对方所持有的资源。可以通过排序或编号等方式来约定资源的获取顺序从而避免循环等待。 破坏请求与保持条件允许线程在请求资源时一次性获取所有需要的资源或者在获取某个资源时释放已经占有的资源。这样可以避免一个线程持有一个资源而等待另一个资源被释放的情况。 使用资源剥夺当一个线程请求资源时如果资源已经被其他线程占有则可以暂时剥夺其他线程对该资源的锁定以满足当前线程的需求。被剥夺的线程可以等待一段时间后再重新申请资源。 使用超时机制在获取锁资源时设置一个超时时间在规定时间内无法获取到资源则放弃获取释放已占有的资源然后重新尝试。 死锁检测和恢复通过检测系统中的死锁情况对存在死锁的线程进行恢复或终止。常见的死锁检测算法包括资源分配图算法和银行家算法。 需要注意的是不同的解决方式适用于不同的场景和问题选择合适的方式需要根据具体情况进行评估。另外预防死锁问题是更好的做法。在设计和实现时尽量避免存在可能导致死锁的条件从根本上杜绝死锁问题的发生。