java线程死锁研究
线程死锁:
a线程锁定了1号资源,下一步需要锁定2号资源。
b线程锁定了2号资源,下一步需要锁定1号资源。
两个线程无限制的等待下去,于是就出现了死锁。
引用网上的实例:
package test; public class TestDeadLock extends Thread { static Object o1 = new Object(), o2 = new Object(); int flag = 0; public void run() { if(flag == 0){ synchronized (o1) { System.out.println("a锁定了刀,想要叉"); try { this.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2){ System.out.println("a 要叉成功"); } } } if(flag == 1){ synchronized (o2) { System.out.println("b锁定了叉,想要刀"); try { this.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1){ System.out.println("b 要刀成功"); } } } } public static void main(String[] args) { TestDeadLock tdl1 = new TestDeadLock(); TestDeadLock tdl2 = new TestDeadLock(); tdl1.flag = 0; tdl2.flag = 1; tdl1.start(); tdl2.start(); } }
避免死锁的方法:
1.让所有的线程按照同样的顺序获得一组锁。这种方法消除了a和b的拥有者分别等待对方的资源的问题。
2.将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个银器对象的锁。于是在获得刀或叉之前都必须获得这个银器的锁。
3.将那些不会阻塞的可获得资源用变量标志出来。当某个线程获得银器对象的锁时,就可以通过检查变量来判断是否整个银器集合中的对象锁都可获得。如果是,它就可以获得相关的锁,否则,就要释放掉银器这个锁并稍后再尝试。
修改方法1:
package test; public class TestDeadLock extends Thread { static Object o1 = new Object(), o2 = new Object(); int flag = 0; String threadName; public TestDeadLock(String threadName){ this.threadName = threadName; } /** * 把两个方法合并到一个同步块中 */ public synchronized void getCanju(){ System.out.println(threadName+"锁定了刀,想要叉"); try { this.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName+"要叉成功"); } public void run() { getCanju(); } public static void main(String[] args) { TestDeadLock tdl1 = new TestDeadLock("线程1"); TestDeadLock tdl2 = new TestDeadLock("线程2"); tdl1.start(); tdl2.start(); } }