學習筆記6:synchronized關鍵字-->線程同步

  1. 爲何要使用關鍵字synchronized?html

    java程序中能夠存在多個線程,可是當多個線程操做同一資源時候,可能會致使數據不一致。java

    區分synchronized方法與synchronized塊:併發

    synchronized方法是一種粗粒度的併發控制,某一時刻,只能有一個線程執行該synchronized方法;dom

    synchronized塊則是一種細粒度的併發控制,只會將塊中的代碼同步,位於方法內、synchronized塊以外的其餘代碼是能夠被多個線程同時訪問到的。ide

  2. 線程同步?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

相關文章
相關標籤/搜索