Java學習(十一):Java鎖Synchronized,對象鎖和類鎖舉例


  Java的鎖分為對象鎖和類鎖。

  1. 當兩個並發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內針對該對象的操作只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。

  2. 然而,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

  3. 尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對該object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

  4. 同步加鎖的是對象,而不是代碼。因此,如果你的類中有一個同步方法,這個方法可以被兩個不同的線程同時執行,只要每個線程自己創建一個的該類的實例即可。

  5. 不同的對象實例的synchronized方法是不相干擾的。也就是說,其它線程照樣可以同時訪問相同類的另一個對象實例中的synchronized方法。

  6. synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中並不自動是synchronized f(){},而是變成了f(){}。繼承類需要你顯式的指定它的某個方法為synchronized方法。

  7.對一個全局對象或者類加鎖時,對該類的所有對象都起作用。

 

類鎖舉例

普通鎖:

 

package ceshi; public class MySynchronized extends Thread { private int val; private Object lock = new Object(); public MySynchronized(int v) { val = v; } public void printVal(int v) { synchronized (lock) { for (int i = 0; i < 50; i++) { System.out.print(v); } } } public void run() { printVal(val); } public static void main(String args[]) { MySynchronized f1 = new MySynchronized(1); f1.start(); MySynchronized f2 = new MySynchronized(2); f2.start(); } }

 

執行結果:2222211111111211111211111111111111111111111111112111111111222222222222222222222222222222222222222222

盡管printVal()對lock變量加鎖,但f1和f2是不同的對象,此時這種鎖在不同的對象之間不起作用。

 

 

對一個全局變量加鎖:

 

 1 package ceshi;  2 
 3 public class MySynchronized extends Thread  4 {  5     private int val;  6     
 7     private static Object lock = new Object();  8     
 9     public MySynchronized(int v) 10  { 11         val = v; 12  } 13     
14     public void printVal(int v) 15  { 16         synchronized (lock) 17  { 18             for (int i = 0; i < 50; i++) 19  { 20  System.out.print(v); 21  } 22  } 23  } 24     
25     public void run() 26  { 27  printVal(val); 28  } 29     
30     public static void main(String args[]) 31  { 32         MySynchronized f1 = new MySynchronized(1); 33  f1.start(); 34         MySynchronized f2 = new MySynchronized(2); 35  f2.start(); 36  } 37 }

 

運行后輸出:1111111111111111111111111111111111111111111111111122222222222222222222222222222222222222222222222222

或者2222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111

由於有全局變量加鎖,盡管是兩個不同的變量f1和f2,printVal()只能依次執行,數字1和2不會同時輸出。

 

 

對整個類加鎖:

 

package ceshi; public class MySynchronized extends Thread { private int val; private static Object lock = new Object(); public MySynchronized(int v) { val = v; } public void printVal(int v) { synchronized (MySynchronized.class) { for (int i = 0; i < 50; i++) { System.out.print(v); } } } public void run() { printVal(val); } public static void main(String args[]) { MySynchronized f1 = new MySynchronized(1); f1.start(); MySynchronized f2 = new MySynchronized(2); f2.start(); } }

 

輸出同上

 

 

另外的鎖例子:

 1 public class MySynchronized extends Thread  2 {  3     private String name;  4     
 5     private String val;  6     
 7     public MySynchronized(String name, String v)  8  {  9         this.name = name; 10         val = v; 11  } 12     
13     public void printVal() 14  { 15         synchronized (val) 16  { 17             while (true) 18  { 19                 System.out.println(name + val); 20  } 21  } 22  } 23     
24     public void run() 25  { 26  printVal(); 27  } 28     
29     public static void main(String args[]) 30  { 31         MySynchronized f1 = new MySynchronized("Foo 1:", "printVal"); 32  f1.start(); 33         MySynchronized f2 = new MySynchronized("Foo 2:", "printVal"); 34  f2.start(); 35  } 36 }
View Code

String常量的特殊性,屬於同一個對象。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM