当两个竞争性动作等待另一个动作完成时,就会发生死锁,因此两者都不会。在Java中,每个对象都有一个锁。为了避免多个线程对单个对象进行并发修改,我们可以使用synchronized关键字,但是一切都是有代价的。synchronized错误使用关键字会导致卡死的系统,称为死锁系统。
考虑在一个实例上有2个线程工作,让线程分别称为First和Second,并说我们有2个资源R1和R2。首先获取R1并需要R2来完成它,而第二获取R2并需要R1来完成。
假设在时间t = 0,
第一个具有R1,第二个具有R2。现在,First在等待R2,而Second在等待R1。此等待是不确定的,这将导致死锁。
public class Example2 { public static void main(String[] args) throws InterruptedException { final DeadLock dl = new DeadLock(); Thread t1 = new Thread(new Runnable() { @Override public void run() { // TODO自动生成的方法存根 dl.methodA(); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { // TODO自动生成的方法存根 try { dl.method2(); } catch (InterruptedException e) { // TODO自动生成的捕获块 e.printStackTrace(); } } }); t1.setName("First"); t2.setName("Second"); t1.start(); t2.start(); } } class DeadLock { Object mLock1 = new Object(); Object mLock2 = new Object(); public void methodA() { System.out.println("方法A等待mLock1 " + Thread.currentThread().getName()); synchronized (mLock1) { System.out.println("方法获得了一个mLock1 " + Thread.currentThread().getName()); try { Thread.sleep(100); method2(); } catch (InterruptedException e) { // TODO自动生成的捕获块 e.printStackTrace(); } } } public void method2() throws InterruptedException { System.out.println("method2等待mLock2 " + Thread.currentThread().getName()); synchronized (mLock2) { System.out.println("方法2获得了mLock2 " + Thread.currentThread().getName()); Thread.sleep(100); method3(); } } public void method3() throws InterruptedException { System.out.println("方法3 mLock1 "+ Thread.currentThread().getName()); synchronized (mLock1) { System.out.println("方法3获得了mLock1 " + Thread.currentThread().getName()); } } }
该程序的输出:
方法A等待mLock1 First method2等待mLock2 Second 方法2获得了mLock2 Second 方法获得了一个mLock1 First 方法3 mLock1 Second method2等待mLock2 First