java資源鎖synchronized說「給我一把 鎖,我能創造一個規矩」

在java多線程編程中,咱們須要對java對象中的資源進行同步管理,確保在同一時刻,只能由同一線程訪問類或者對象中的資源,這樣能夠防止因爲幾個線程共享同一資源致使不可知的後果。java

方法之一就是利用資源鎖(synchronized),廢話少說,先上例子編程

例子一多線程

public class S_1 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_1().start();
  }
 }
}ide

class Thread_1 extends Thread{
 @Override
 public synchronized void run() {
  for(int i=0;i<100;i++){
   System.out.println(i);
  }
 }
 
}this

例子二:線程

public class S_2 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_2().start();
  }
 }
}
class Thread_2 extends Thread{
 @Override
 public void run(){
  synchronized(this){
   for(int i=0;i<100;i++){
    System.out.println(i);
   }
  }
 }
}
對象

例子三:繼承


public class S3 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_3().start();
  }
 }
}
class Thread_3 extends Thread{
 public synchronized static void show(){
  for(int i=0;i<100;i++){
   System.out.println(i);
  }
 }
 @Override
 public void run(){
  show();
 }資源

}
同步

例子四:

public class S_4 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   String lock = "lock";
   new Thread_4(lock).start();
  }
 }
}
class Thread_4 extends Thread{
 private String lock ;
 public Thread_4(String lock){
  this.lock = lock ;
 }
 @Override
 public void run(){
  synchronized(lock){
   for(int i=0;i<100;i++){
    System.out.println(i);
   }
  }
 }
 
}
以上四個例子是用五個線程從0-99進行打印,他們都是按照前後順序從0-99進行打印的嗎?若是你的答案是按順序依次打印的話,那你就錯了,下邊我一一來說解下

例子一,沒有按照前後順序進行打印。咱們對run方法進行了加鎖,按理說是該按照前後順序進行打印的,可是爲何結果與咱們想象的不同呢?因爲咱們起五個線程的時候,咱們建立了五個Thread_1對象,這樣每一個線程都獲取了一個對象,每一個線程都獲取了本身對象中run方法的鎖,因此,這裏的資源鎖是沒有意義的,若是要讓這裏的鎖起做用,除非該Thread_1是單例模式的,這樣這些線程都共享一個對象,纔會按照前後順序獲取鎖

例子二,沒有按照前後順序進行打印。咱們對run方法中的一部分代碼進行了synchronized塊保護,也應該按照每一個線程依次打印,但爲何仍是沒有依次打印呢?因爲咱們synchronized(this)中的this在五個線程中是沒有共享的,五個線程中的this都不同,這樣至關於對五個對象進行資源塊進行保護,五個線程依然可以同時獲取synchronized(this)方法中的代碼執行的鎖

例子三,按照前後順序打印。這個例子能夠和例子一對應起來看,咱們是在show方法上加的鎖,而且show方法是static的,這樣這裏方法就是類方法,被因此對象共享的,當咱們起五個線程,這五個線程對show方法是共享的,並且該方法被加鎖了,當線程來訪問的時候,首先看這個方法是否被其餘線程使用,若是正在被其餘對象使用,對不起,你先等着,等下一個線程用完了,退出了的時候,線程池中輪到你的時候,你才能執行該方法

例子四,按照前後順序打印。這個例子能夠和例子四對應起來看,首先咱們來看下例子4,類Thread_4是一個繼承Thread的線程類,他有一個私有變量lock,在其run方法中,咱們用鎖塊對要打印的語句進行保護,咱們在啓動線程的時候,經過構造方法,給Thread_4的lock變量進行賦值,因爲咱們啓動的五個線程中,每一個Thread對象的lock變量的值都是同一個,即五個線程共享變量lock,因此要執行被synchronized方法鎖起來的語句,也必須得到相應的鎖纔可以執行,對比例子一種,this的值在每一個線程中不同的

 

最後總結

若是咱們想經過synchronized來修辭方法,來達到在同一時刻,該方法只能被同一線程訪問的話,有兩個條件

條件一:線程對象是一個單例類

條件二:synchronized修飾的方法是static的

若是咱們想經過synchronized方法來達到在同一時刻,被保護的語句塊只能被同一線程訪問,其條件是

synchronized方法中傳入的對象必須是共享的,即傳入的對象必須是同樣的

 

但願這篇博文對你有用,若是我對synchronized認識不到位的地方,請多多指教

相關文章
相關標籤/搜索