爲何要使用關鍵字synchronized?html
java程序中能夠存在多個線程,可是當多個線程操做同一資源時候,可能會致使數據不一致。java
區分synchronized方法與synchronized塊:併發
synchronized方法是一種粗粒度的併發控制,某一時刻,只能有一個線程執行該synchronized方法;dom
synchronized塊則是一種細粒度的併發控制,只會將塊中的代碼同步,位於方法內、synchronized塊以外的其餘代碼是能夠被多個線程同時訪問到的。ide
線程同步?this
所謂線程同步就是若干個線程都須要使用一個synchronized(同步)修飾的方法,即程序中的若干個線程都須要使用一個方法,而這個方法用synchronized給予修飾,那麼多個線程調用該方法時候必須遵照同步機制:spa
當一個線程A使用synchronized方法時,其餘線程想使用這個synchronized方法就必須等待,直至前後才能A使用完畢。即對於synchronized修飾的方法,一次只容許一個線程訪問,其餘線程只能等待。線程
2.1 首先看看synchronized方法: code
public synchronized void saveOrTake(int amount){ // 這裏是同步方法 } public void saveOrTake(int amount){ synchronized(this){ // 這裏是同步塊 } }
//完整代碼段:orm
public class Test01Bank { /** * @param args * @author 牧羊的伯格女皇 * 2015-11-07 */ public static void main(String[] args) { Bank bank = new Bank(); bank.setMOney( 200 ); Thread accountant = new Thread(bank); // 會計 Thread cashier = new Thread(bank); // 出納 accountant.setName("會計"); cashier.setName("出納"); accountant.start(); cashier.start(); } } public class Bank implements Runnable { int money = 200; public void setMOney(int n ){ money = n; } @Override public void run() { if(Thread.currentThread().getName().equals("會計")){ saveOrTake(300); }else if(Thread.currentThread().getName().equals("出納")){ saveOrTake(150); } } //存取 同步方法 public synchronized void saveOrTake(int amount){ //synchronized(this){ // 同步塊 System.out.println( "首先看看帳上原始金額爲: " + money ); if(Thread.currentThread().getName().equals("會計")){ for(int i=0;i<3;i++){ money += amount/3; System.out.println(Thread.currentThread().getName() +" 存入 "+amount/3+" 帳上有 " +money+" 萬,稍歇會再存"); try { Thread.sleep( 1000 ); // 這時候出納仍不能使用該方法,由於sleep並無釋放該對象鎖。 } catch (InterruptedException e) { e.printStackTrace(); } } }else if(Thread.currentThread().getName().equals("出納")){ for(int i=0;i<3;i++){ money -= amount/3; System.out.println(Thread.currentThread().getName() +" 取出 "+amount/3+" 帳上有 " +money+" 萬,稍歇會再取"); try { Thread.sleep( 1000 ); // 這時候 會計仍不能使用該方法,由於sleep並無釋放該對象鎖。 } catch (InterruptedException e) { e.printStackTrace(); } } } //} } }
試觀察運行結果:
2.2 synchronized同步塊:
synchronized塊寫法:
synchronized(object){
}
表示線程在執行的時候會將object對象上鎖。(注意這個對象能夠是任意類的對象,也能夠使用this關鍵字)。
這樣就能夠自行規定上鎖對象。
import java.util.Random; public class Demo14synchronized { public static void main(String[] args) { SellTickOp s = new SellTickOp(30); Thread t1 = new Thread( s, "張三"); Thread t2 = new Thread( s, "李四"); Thread t3 = new Thread( s, "王五"); t1.start(); t2.start(); t3.start(); } } class SellTickOp implements Runnable{ int tickets; Random r = new Random(); public SellTickOp(int tickets){ this.tickets = tickets; } @Override public void run() { while(true){ synchronized(this){ // 這裏使用的是同步塊 if( tickets > 0 ){ try { Thread.sleep( r.nextInt(800) ); System.out.println( Thread.currentThread().getName() +" 在購買第 " +(tickets--) + " 張票" ); } catch (InterruptedException e) { e.printStackTrace(); } } else{ return; } } } } }
synchronized關鍵字更多理解: http://www.cnblogs.com/mengdd/archive/2013/02/16/2913806.html