java執行緒互斥是為了保證,同一時刻最多隻有一個執行緒執行該段程式碼。那麼它的出現又是為了解決什麼問題呢?賬戶存取款,在同一時間段只能讓一個人進行操作。

下面來看一個簡單例項(多執行緒帶來的問題):

public class TraditionalThreadSynchronized {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new TraditionalThreadSynchronized().init();
	}
	
	private void init(){
		//此方法同時啟動兩個執行緒,去呼叫同一個方法的列印名字
		final Outputer outputer = new Outputer();
		new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					outputer.output("zhangxiaoxiang");
				}				
			}
		}).start();
		
		new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					outputer.output3("lihuoming");
				}
				
			}
		}).start();
		
	}

	static class Outputer{
		
		public void output(String name){
			int len = name.length();
//			synchronized (Outputer.class) 
//			{
				for(int i=0;i<len;i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
//			}
		}
		
	}
}

列印結果為:


解決以上問題:

新增synchronized的關鍵字,即解開註釋即可。

列印結果:


總結:

當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。即當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,其他執行緒對object中所有其它synchronized(this)同步程式碼塊的訪問將被阻塞。

注意:要互斥,必須讓鎖子是同一把。以上的demo中,兩個執行緒都用的是同一個new出來的output,所以output就是同一個物件。

簡答說明:

public class Test implements Runnable {

    public int cash = 100;

    public synchronized void m() {
        System.out.println("m檢視賬戶,餘額為"+cash);
        try {
             Thread.sleep(2000);
        } catch (InterruptedException e) {
             e.printStackTrace();
        }
        cash = cash - 100;
        System.out.println("cash1 = " + cash);
    }

    public synchronized void run() {
        System.out.println("run檢視賬戶,餘額為"+cash);
        cash += 1000;
        try {
            Thread.sleep(5000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
        System.out.println("cash2 = " + cash);
    }

    public static void main(String[] args) {
        Test test = new Test();
        Thread thrad = new Thread(test);
        thrad.start();
        test.m();
    }
}

新增synchronized關鍵字後可以看出。只要m或者run進行對賬戶進行操作,不論中途多長時間,或者睡眠多長時間,執行緒都要執行完這個方法以後才會執行其他的方法。兩個方法都必須加synchronized關鍵字,並且兩者鎖定同一物件(此處鎖定的物件是test物件)。也就是說,只要有一個執行緒進入test物件的任意一個加了鎖的方法,其他執行緒就不能訪問這個物件里加了相同鎖的方法了。