java多個例項物件執行緒同步無效的原因以及解決方案
阿新 • • 發佈:2019-01-01
【原因】:synchronized用法沒搞清楚
下面就直接舉例子了!
【情況1】:單例項物件多執行緒
public class Demo3 { Tlwindow twd1,twd2,twd3; //定義三個視窗 public static void main(String[] args){ Demo3 demo3=new Demo3(); } public Demo3(){ twd1=new Tlwindow(); Thread t1=new Thread(twd1); Thread t2=new Thread(twd1); Thread t3=new Thread(twd1); t1.start(); t2.start(); t3.start(); } } //賣票視窗類 class Tlwindow implements Runnable{ int num=2000; //假設共有2000張票 //重寫run //不斷地賣票 public void run(){ while(true){ synchronized(this){ try{ Thread.sleep(1000); }catch(Exception $e){ System.out.println("異常"); } if(this.num>0){ System.out.println(Thread.currentThread().getName()+":當前正在賣"+num+"張票"); num--; }else{ break; } } } } }
【情況2】:多例項物件多執行緒
public class Demo3 { Tlwindow twd1,twd2,twd3; //定義三個視窗 public static void main(String[] args){ Demo3 demo3=new Demo3(); } public Demo3(){ twd1=new Tlwindow(); twd2=new Tlwindow(); twd3=new Tlwindow(); Thread t1=new Thread(twd1); Thread t2=new Thread(twd2); Thread t3=new Thread(twd3); t1.start(); t2.start(); t3.start(); } } //賣票視窗類 class Tlwindow implements Runnable{ int num=2000; //假設共有2000張票 //重寫run //不斷地賣票 public void run(){ while(true){ synchronized(Tlwindow.class){ try{ Thread.sleep(1000); }catch(Exception $e){ System.out.println("異常"); } if(this.num>0){ System.out.println(Thread.currentThread().getName()+":當前正在賣"+num+"張票"); num--; }else{ break; } } } } }
【實現效果】:如下圖
【總結】:
synchronized(引數){ //注意這個“引數”,如果寫this範圍是類的一個例項物件,如果寫"類名.class"範圍是這個類的所有例項物件
//你的程式碼
}
【更詳細的原理說明】:
- 某個物件例項內,synchronized (this或類名){}可以防止多個執行緒同時訪問這個物件的synchronized方法(如果一個物件有多個synchronized方法,只要一個線 程訪問了其中的一個synchronized方法,其它執行緒不能同時訪問這個物件中任何一個synchronized方法)。這時,不同的物件例項的 synchronized方法是不相干擾的。也就是說,其它執行緒照樣可以同時訪問相同類的另一個物件例項中的synchronized方法;
- 某個類的範圍,synchronized (類名.class){}防止多個執行緒同時訪問這個類中的synchronized 裡面的程式碼。它可以對類的所有物件例項起作用。