1. 程式人生 > >java 同步鎖問題(synchronized)

java 同步鎖問題(synchronized)

Java中cpu分給每個執行緒的時間片是隨機的並且在java中好多都是多個執行緒共用一個資源,比如火車賣票,火車票是一定的,但賣火車票的視窗到處都有,每個視窗就相當於一個執行緒,這麼多的執行緒共用所有的火車票這個資源。如果在一個時間點上,兩個執行緒同時使用這個資源,那他們取出的火車票是一樣的(座位號一樣),這樣就會給乘客造成麻煩。比如下面程式:

[java]  view plain  copy  print ?
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.                 if
    (this.ticket>0){  
  11.                     //休眠1s秒中,為了使效果更明顯,否則可能出不了效果  
  12.                     try {  
  13.                         Thread.sleep(1000);  
  14.                     } catch (Exception e) {  
  15.                         e.printStackTrace();  
  16.                     }  
  17.                     System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");  
  18.                 }  
  19.               
  20.         }  
  21.     }  
  22.       
  23.      public static void main(String args[]){  
  24.          Runnable_demo demo=new Runnable_demo();  
  25.          //基於火車票建立三個視窗  
  26.          new Thread(demo,"a").start();  
  27.          new Thread(demo,"b").start();  
  28.          new Thread(demo,"c").start();  
  29.      }  
  30.       
  31. }  

程式執行結果:


我們可以看到c號視窗和和b號視窗都賣出了10號票,並且a號和b號視窗分別賣出了0號和-1號票。造成這種情況的原因是1、c執行緒和b執行緒在ticket=10的時候,c執行緒取出10號票以後,ticket還沒來的及減1,b執行緒就取出了ticket此時ticket還等於10;2、在ticket=1時,c執行緒取出了1號票,ticket還沒來的及減1,a、b執行緒就先後進入了if判斷語句,這時ticket減1了,那麼當a、b執行緒取票的時候就取到了0號和-1號票。

出現了上述情況怎樣改變呢,我們可以這樣做:當一個執行緒要使用火車票這個資源時,我們就交給它一把鎖,等它把事情做完後在把鎖給另一個要用這個資源的執行緒。這樣就不會出現上述情況。 實現這個鎖的功能就需要用到synchronized這個關鍵字。

synchronized這個關鍵字有兩種用法1、放方法名前形成同步方法;2、放在塊前構成同步塊。

1、使用同步方法將上面的例子該為:

[java]  view plain  copy  print ?
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.                 if(this.ticket>0){  
  11.                     //休眠1s秒中,為了使效果更明顯,否則可能出不了效果  
  12.                     try {  
  13.                         Thread.sleep(1000);  
  14.                     } catch (Exception e) {  
  15.                         e.printStackTrace();  
  16.                     }  
  17.                     this.sale();  
  18.                 }  
  19.               
  20.         }  
  21.     }  
  22.       
  23.     public synchronized void sale(){  
  24.         if(this.ticket>0){  
  25.             System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");  
  26.         }  
  27.     }  
  28.       
  29.      public static void main(String args[]){  
  30.          Runnable_demo demo=new Runnable_demo();  
  31.          //基於火車票建立三個視窗  
  32.          new Thread(demo,"a").start();  
  33.          new Thread(demo,"b").start();  
  34.          new Thread(demo,"c").start();  
  35.      }  
  36.       
  37. }  

程式的輸出結果為:

2、使用同步塊修改上面的例子:

[java]  view plain  copy  print ?
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.             <span style="color:#ff0000">synchronized</span>(this){  
  11.                 if(this.ticket>0){  
  12.                     //休眠1s秒中,為了使效果更明顯,否則可能出不了效果  
  13.                     try {  
  14.                         Thread.sleep(1000);  
  15.                     } catch (Exception e) {  
  16.                         e.printStackTrace();  
  17.                     }  
  18.                     System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");  
  19.                 }  
  20.             }  
  21.               
  22.         }  
  23.     }  
  24.       
  25.      public static void main(String args[]){  
  26.          Runnable_demo demo=new Runnable_demo();  
  27.          //基於火車票建立三個視窗  
  28.          new Thread(demo,"a").start();  
  29.          new Thread(demo,"b").start();  
  30.          new Thread(demo,"c").start();  
  31.      }  
  32.       
  33. }  

程式的輸出結果:



摘自:http://blog.csdn.net/lianqiangjava/article/details/12652201/         侵刪。