abstract: synchronized ()方法解决了线程同步的问题,却带来新的问题——线程死锁。线程死锁是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 public class sisuo { public s
synchronized ()方法解决了线程同步的问题,却带来新的问题——线程死锁。线程死锁是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
public class sisuo { public static void main(String[] args) { Object obj1=new Object(); Object obj2=new Object(); DeadLockThread1 diedLock1=new DeadLockThread1(obj1,obj2); DeadLockThread2 diedLock2=new DeadLockThread2(obj1,obj2); diedLock1.start(); diedLock2.start(); } } class DeadLockThread1 extends Thread{ private Object obj1; private Object obj2; public DeadLockThread1(Object obj1,Object obj2){ this.obj1=obj1; this.obj2=obj2; } public void run() { synchronized (obj1) { try{ Thread.sleep(100); synchronized (obj2) { System.out.println("Thread1执行成功"); } }catch (InterruptedException e) { e.printStackTrace(); } } } } class DeadLockThread2 extends Thread{ private Object obj1; private Object obj2; public DeadLockThread2(Object obj1,Object obj2){ this.obj1=obj1; this.obj2=obj2; } public void run() { synchronized (obj2) { try{ Thread.sleep(100); synchronized(obj1) { System.out.println("Thread2执行成功"); } }catch (InterruptedException e) { e.printStackTrace(); } } } }
在这个例子中,线程1和线程2同时启动。线程1锁定了obj1并等待obj2释放, 线程2锁定了obj2并等待obj1释放,因此陷入死循环,无法得出执行结果。由于时间片随机分配,死锁并非一定发生,尤其当程序语句并不多的时候,可能线程1执行完后才执行线程2,从而运行成功。但本例中在两个步骤之间加入Thread.sleep(100);设置0.1秒的休息时间,死锁必然会发生。
java没有检测死锁的机制,因此在设计时一定要合理避免死锁。如果把class DeadLockThread2的synchronized (obj1)和synchronized (obj2)调换顺序就能看到执行结果:
避免死锁最简单的方法就是设置相同的访问顺序或在所有线程的第一部添加一把相同的锁。虽然这样会减缓程序的运行时间,消耗更多的资源。