在多線程中如何找到安全問題所在:
1,明確哪些代碼是多線程運行代碼
2,明確共享數據
3,明確多線程運行代碼中哪些代碼是操作共享數據的
靜態的同步方法中,使用鎖是該方法所在類的字節碼文件對象,即 類名.class
前天俺們談到了加鎖,但是在使用加鎖的同時又會帶來一個問題,就是死鎖。什么叫死鎖?
所謂死鎖: 是指兩個或兩個以上的進程在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。
那么為什么會產生死鎖呢?
1.因為系統資源不足。
2.進程運行推進的順序不合適。
3.資源分配不當。
學過操作系統的朋友都知道:產生死鎖的條件有四個:
1.互斥條件:所謂互斥就是進程在某一時間內獨占資源。
2.請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
3.不剝奪條件:進程已獲得資源,在末使用完之前,不能強行剝奪。
4.循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
例如:
死鎖是因為多線程訪問共享資源,由於訪問的順序不當所造成的,通常是一個線程鎖定了一個資源A,而又想去鎖定資源B;在另一個線程中,鎖定了資源B,而又想去鎖定資源A以完成自身的操作,兩個線程都想得到對方的資源,而不願釋放自己的資源,造成兩個線程都在等待,而無法執行的情況。
分析死鎖產生的原因不難看出是由訪問共享資源順序不當所造成的,下面寫一個造成線程死鎖的例子,希望能對大家理解多線程死鎖問題有進一步的理解!如果有人需要編寫多線程的系統,當操作共享資源時一定要特別的小心,以防出現死鎖的情況!
package com.oyqh; public class RunnableTest implements Runnable { private int flag = 1; private static Object obj1 = new Object(), obj2 = new Object(); public void run() { System.out.println("flag=" + flag); if (flag == 1) { synchronized (obj1) { System.out.println("我已經鎖定obj1,休息0.5秒后鎖定obj2去!"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2) { System.out.println("1"); } } } if (flag == 0) { synchronized (obj2) { System.out.println("我已經鎖定obj2,休息0.5秒后鎖定obj1去!"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj1) { System.out.println("0"); } } } } public static void main(String[] args) { RunnableTest run01 = new RunnableTest(); RunnableTest run02 = new RunnableTest(); run01.flag = 1; run02.flag = 0; Thread thread01 = new Thread(run01); Thread thread02 = new Thread(run02); System.out.println("線程開始嘍!"); thread01.start(); thread02.start(); } }
<span style="font-size:18px;">package com.oyqh; public class RunnableTest implements Runnable { private int flag = 1; private Object obj1 = new Object(), obj2 = new Object(); public void run() { System.out.println("flag=" + flag); if (flag == 1) { synchronized (obj1) { System.out.println("我已經鎖定obj1,休息0.5秒后鎖定obj2去!"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj2) { System.out.println("1"); } } } if (flag == 0) { synchronized (obj2) { System.out.println("我已經鎖定obj2,休息0.5秒后鎖定obj1去!"); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj1) { System.out.println("0"); } } } } public static void main(String[] args) { RunnableTest run01 = new RunnableTest(); RunnableTest run02 = new RunnableTest(); run01.flag = 1; run02.flag = 0; Thread thread01 = new Thread(run01); Thread thread02 = new Thread(run02); System.out.println("線程開始嘍!"); thread01.start(); thread02.start(); } }</span>
這樣就產生了死鎖,這是我們過多的使用同步而產生的。我們在Java中使用synchonized的時候要考慮這個問題,如何解決死鎖,大家可以從死鎖的四個條件去解決,只要破壞了一個必要條件,那么我們的死鎖就解決了。在java中使用多線程的時候一定要考慮是否有死鎖的問題.
The other example:
one:
<span style="font-size:18px;">class Ticket implements Runnable { private int tick=100; Object obj=new Object(); boolean flag=true; public void run(){ if (flag) { while (true) { synchronized(obj){ show(); } } } else while (true) show(); } public synchronized void show(){ synchronized(obj){ if (tick>0) { try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"...code..."+tick--); } } } } class DeadLockDemo { public static void main(String[] args){ Ticket t=new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); try{Thread.sleep(10);} catch(Exception e){} t.flag=false; t2.start(); } }</span> [java] view plain copy <span style="font-size:18px;"></span> [java] view plain copy <span style="font-size:18px;">two:</span> [java] view plain copy <span style="font-size:18px;">class TestDeadLock { private boolean flag; TestDeadLock(boolean flag){ this.flag=flag; } public void run(){ if (flag) { synchronized(MyLock.locka){ System.out.println("if's locka"); synchronized(MyLock.lockb){ System.out.println("if's lockb"); } } } else{ synchronized(MyLock.lockb){ System.out.println("else's lockb"); synchronized(MyLock.locka){ System.out.println("else's locka"); } } } } } class MyLock { static Object locka=new Object(); static Object lockb=new Object(); } class DeadLockTest { public static void main(String[] args){ Thread t1=new Thread(new TestDeadLock(true)); Thread t2=new Thread(new TestDeadLock(false)); t1.start(); t2.start(); } }</span> [java] view plain copy <span style="font-size:18px;"></span>