《跟我学Java面向对象程序设计技术及应用——线程死锁技术及解决方案.docx》由会员分享,可在线阅读,更多相关《跟我学Java面向对象程序设计技术及应用——线程死锁技术及解决方案.docx(15页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、跟我学Java面向对象程序设计技术及应用线程死锁技术及解决方案 1.1线程死锁技术及解决方案 1.1.1线程死锁及示例 1、为什么会产生出死锁 线程死锁时,第一个线程等待第二个线程释放资源,而同时第二个线程又在等待第一个线程释放资源。导致死锁的根源在于不适当地运用“synchronized”关键词来管理线程对特定对象的访问。 “synchronized”关键词的作用是,确保在某个时刻只有一个线程被允许执行特定的代码块,因此,被允许执行的线程首先必须拥有对变量或对象的排他性访问权。当线程访问对象时,线程会给对象加锁,而这个锁导致其它也想访问同一对象的线程被阻塞,直至第一个线程释放它加在对象上的锁
2、。 2、线程死锁示例 (1)SomeThreadOne类代码 package com.px1987.threaddemo; public class SomeThreadOne extends Thread private Object someResourceOne =null; private Object someResourceTwo =null; public SomeThreadOne() public SomeThreadOne(Object someResourceOne,Object someResourceTwo) this.someResourceOne=someReso
3、urceOne; this.someResourceTwo=someResourceTwo; public void run() synchronized (someResourceOne) System.out.println(线程+this.getClass().getName()+正在锁定资源1); try Thread.sleep(50); catch (InterruptedException e) synchronized (someResourceTwo) System.out.println(线程+this.getClass().getName()+正在锁定资源2); (2)S
4、omeThreadTwo类代码 package com.px1987.threaddemo; public class SomeThreadTwo extends Thread private Object someResourceOne =null; private Object someResourceTwo =null; public SomeThreadTwo() public SomeThreadTwo(Object someResourceOne,Object someResourceTwo) this.someResourceOne=someResourceOne; this.s
5、omeResourceTwo=someResourceTwo; public void run() synchronized (someResourceTwo) System.out.println(线程+this.getClass().getName()+正在锁定资源2); try Thread.sleep(50); catch (InterruptedException e) synchronized (someResourceOne) System.out.println(线程+this.getClass().getName()+正在锁定资源1); (3)DeadlockTest类代码
6、package com.px1987.threaddemo; public class DeadlockTest public static void main(String args) final Object resource1 = 锁定资源1; final Object resource2 = 锁定资源2; Thread someThreadOne = new SomeThreadOne(resource1,resource2); someThreadOne.start(); Thread someThreadTwo = new SomeThreadTwo(resource1,resou
7、rce2); someThreadTwo.start(); (4)执行的结果 该程序运行后将永远不会自己退出,除非你Ctrl+C,而且运行时CPU会直接飙到100%。 3、线程死锁示例 (1)SomeThreadOne类代码示例 package com.px1987.threaddemo; public class SomeThreadOne extends Thread private String dataOne; private String dataTwo; public SomeThreadOne() public SomeThreadOne(String dataOne,Strin
8、g dataTwo) this.dataOne=dataOne; this.dataTwo=dataTwo; public void run() /* *同步中又有同步,就可能死锁 */ synchronized(dataOne) System.out.println(Thread.currentThread().getName()+锁定dataOne); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); synchronized(dataTwo) System.out.println(Thr
9、ead.currentThread().getName()+锁定dataTwo); (2)SomeThreadTwo类代码 package com.px1987.threaddemo; public class SomeThreadTwo extends Thread private String dataOne; private String dataTwo; public SomeThreadTwo() public SomeThreadTwo(String dataOne,String dataTwo) this.dataOne=dataOne; this.dataTwo=dataTwo
10、; public void run() /* *同步中又有同步,就可能死锁 */ synchronized(dataTwo) System.out.println(Thread.currentThread().getName()+锁定dataTwo); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); synchronized(dataOne) System.out.println(Thread.currentThread().getName()+锁定dataOne); (3)ThreadDe
11、adLockDemo类代码 package com.px1987.threaddemo; public class ThreadDeadLockDemo public ThreadDeadLockDemo() public static void main(String args) /* * 定义线程中所需要的资源 */ String someDataToDataOne=这是给线程一中的dataOne的赋值; String someDataToDataTwo=这是给线程二中的dataTwo的赋值; /* * 创建出2个不同的线程 */ SomeThreadOne threadOneObj=ne
12、w SomeThreadOne(someDataToDataOne,someDataToDataTwo); SomeThreadTwo threadTwoObj=new SomeThreadTwo(someDataToDataOne,someDataToDataTwo); /* * 分别启动两个线程 */ threadOneObj.start(); threadTwoObj.start(); (4)执行的结果 4、不正确的线程同步而造成的线程死锁示例 (1)PushDataThread类的代码示例 package com.px1987.threaddemo; public class Push
13、DataThread extends Thread private SynchronizedStack synchronizedStack=null; public PushDataThread(SynchronizedStack synchronizedStack) this.synchronizedStack=synchronizedStack; Override public void run() for(int loopIndex = 0; loopIndex 100; loopIndex+) try Thread.sleep(10); catch (InterruptedExcept
14、ion e) e.printStackTrace(); synchronizedStack.pushSomeOneData(new Integer(loopIndex).toString(); (2)PopDataThread类的代码示例 package com.px1987.threaddemo; public class PopDataThread extends Thread private SynchronizedStack synchronizedStack=null; public PopDataThread(SynchronizedStack synchronizedStack)
15、 this.synchronizedStack=synchronizedStack; Override public void run() for(int loopIndex = 0; loopIndex 100; loopIndex+) try System.out.println(synchronizedStack.popSomeOneData(); catch (Exception e) e.printStackTrace(); (3)SynchronizedStack类的代码示例 package com.px1987.threaddemo; import java.util.Linke
16、dList; public class SynchronizedStack private LinkedList allDataList = new LinkedList(); /* *保存数据的方法 */ public synchronized void pushSomeOneData(Object someOneData) System.out.println(开始压栈: + someOneData); synchronized (allDataList) allDataList.addLast(someOneData); notify(); System.out.println(结束压栈
17、: + someOneData); /* *恢复数据的方法 */ public synchronized Object popSomeOneData() throws Exception System.out.println(开始弹栈); synchronized (allDataList) if (allDataList.size() = 0) wait(); return allDataList.removeLast(); 注意同步方法中又出现同步代码段。 (4)TestSynchronizedStack类的代码示例 该程序构造了一个模拟的Stack,并启动了两个线程分别操作该Stack。
18、一个线程向Stack 中添加数据,另外一个线程从Stack 中取出数据并打印。 package com.px1987.threaddemo; public class TestSynchronizedStack public static void main(String args) final SynchronizedStack stack = new SynchronizedStack(); new PushDataThread(stack).start(); new PopDataThread(stack).start(); (5)执行的结果 运行程序后就会发现程序输出相关的信息后,再也
19、没有后续输出了产生了死锁。 5、改进的代码示例 (1)SynchronizedStack类的代码示例 package com.px1987.threaddemo; import java.util.LinkedList; public class SynchronizedStack private LinkedList allDataList = new LinkedList(); /* *保存数据的方法 */ public synchronized void pushSomeOneData(Object someOneData) System.out.println(开始压栈: + someOneData); allDataList.addLast(someOneData); notify(); System.out.println(结束压栈: + someOneData); /* *恢复数据的方法 */ public synchronized Object popSomeOneData() throws Exception System.out.println(开始弹栈); if (allDataList.size() = 0) wait(); return allDataList.removeLast(); (2)执行的结果
限制150内