java中,線程互斥是爲了保證在同一時刻,只有一個線程在訪問一段特定的代碼或者一個特定的變量。java
看一個多線程使用同一個對象操做引發的問題:多線程
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package
com.model.elgin.thread; public class TestThread4 { public static void main( String [] args) { init(); } private static void init(){ final PrintString ps= new PrintString(); //開啓2個線程,分別使用同一個ps對象來打印不一樣的字符串 new Thread( new Runnable() { @Override public void run() { while (true){ ps.print( "Chinajiangsuchangzhou" ); } } }).start(); new Thread( new Runnable() { @Override public void run() { while (true){ ps.print( "Americanlalala" ); } } }).start(); } } class PrintString{ //按單個字符打印字符串 public void print( String name){ for ( int i = 0 ; i < name.length(); i++) { System.out.print(name.charAt(i)); } System.out.println(); } } |
這時候,能夠從結果中偶爾發現這樣的輸出:併發
咱們發現,2個線程中的不一樣的字符串內容出現了錯亂,這就是在多個線程同時訪問同一個資源(此處爲ps對象)時出現的問題。ide
那麼這個問題該如何處理呢?this
咱們能夠經過對多個線程訪問的公共方法或者代碼塊加鎖來實現,保證在同一時刻只有一個線程在訪問處理資源。spa
有2種方式來實現鎖:.net
1)、在PrintString類的print方法上增長synchronized關鍵字來給方法加鎖。在已有線程在調用此方法的時候,其它的線程不能調用它。線程
2)、經過同步代碼塊來給一段代碼加鎖,修改以下:對象
1
2 3 4 5 6 7 8 9 10 11 |
class
PrintString{ //按單個字符打印字符串 public void print( String name){ synchronized ( this ){ for ( int i = 0 ; i < name.length(); i++) { System.out.print(name.charAt(i)); } System.out.println(); } } } |
修改事後,再次運行,上述問題再也不出現。blog
總結:
當兩個併發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程獲得執行。另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊。即當一個線程訪問object的一個synchronized(this)同步代碼塊時,其餘線程對object中全部其它synchronized(this)同步代碼塊的訪問將被阻塞。
注意:要互斥,必須讓鎖是同一把。以上的demo中,兩個線程都用的是同一個new出來的ps對象,因此是同一個對象。