synchronized關鍵字

介紹synchronized關鍵字以前有必要闡述一下線程安全的概念。「非線程安全」會在多個線程對同一個對象中的實例變量進行併發訪問時發生,產生的後果就是「髒讀」,也就是取到的數據實際上是被更改過的,若是是方法內部的私有變量不存在「非線程安全」的問題;而「線程安全」就是得到的實例變量的值是通過同步處理的,不會出現髒讀的現象。synchronized就是保證同步的。java

package chapter2.synch.method;

public class MyObject {
	
	synchronized public void methodA() {
		try {
			System.out.println("begin methodA threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
			Thread.sleep(5000);
			System.out.println("end methodA threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	synchronized public void methodB() {
		try {
			System.out.println("begin methodB threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
			Thread.sleep(2000);
			System.out.println("end methodB threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void methodC() {
		try {
			System.out.println("begin methodC threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
			Thread.sleep(2000);
			System.out.println("end methodC threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void methodD() {
		try {
			synchronized (this) {
				System.out.println("begin methodD threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
				Thread.sleep(2000);
				System.out.println("end methodD threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void methodE() {
		try {
			Object object = new Object();
			synchronized (object) {
				System.out.println("begin methodE threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
				Thread.sleep(2000);
				System.out.println("end methodE threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void methodF(Object object) {
		try {
			synchronized (object) {
				System.out.println("begin methodF threadName="+Thread.currentThread().getName()+"--beginTime:"+System.currentTimeMillis());
				Thread.sleep(2000);
				System.out.println("end methodF threadName="+Thread.currentThread().getName()+"--endTime:"+System.currentTimeMillis());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

package chapter2.synch.method;

public class ThreadA extends Thread{
	
	private MyObject myObject;

	public MyObject getMyObject() {
		return myObject;
	}

	public void setMyObject(MyObject myObject) {
		this.myObject = myObject;
	}
	
	@Override
	public void run() {
		super.run();
		myObject.methodA();
	}

}


package chapter2.synch.method;

public class ThreadB extends Thread{
	
	private MyObject myObject;

	public MyObject getMyObject() {
		return myObject;
	}

	public void setMyObject(MyObject myObject) {
		this.myObject = myObject;
	}
	
	@Override
	public void run() {
		super.run();
		myObject.methodB();
	}

}

package chapter2.synch.method;

public class Run {

	public static void main(String[] args) {
		MyObject myObject = new MyObject();
		ThreadA threadA = new ThreadA();
		threadA.setMyObject(myObject);
		threadA.setName("A");
		
		ThreadB threadB = new ThreadB();
		threadB.setMyObject(myObject);
		threadB.setName("B");
		
		threadA.start();
		threadB.start();
		
	}
}

 運行結果:(同步執行)安全

begin methodA threadName=A--beginTime:1560936665128
end methodA threadName=A--endTime:1560936670128
begin methodB threadName=B--beginTime:1560936670128
end methodB threadName=B--endTime:1560936672128併發

 

若是ThreadB 修改爲myObject.methodC();異步

運行結果:(異步執行)ide

begin methodC threadName=B--beginTime:1560936788821
begin methodA threadName=A--beginTime:1560936788821
end methodC threadName=B--endTime:1560936790821
end methodA threadName=A--endTime:1560936793821this

 

若是ThreadB 修改爲myObject.methodD();spa

運行結果:(同步執行)線程

begin methodD threadName=B--beginTime:1560936856169
end methodD threadName=B--endTime:1560936858169
begin methodA threadName=A--beginTime:1560936858169
end methodA threadName=A--endTime:1560936863169

code

若是ThreadB 修改爲myObject.methodE();對象

運行結果:(異步執行)

begin methodE threadName=B--beginTime:1560936949062
begin methodA threadName=A--beginTime:1560936949062
end methodE threadName=B--endTime:1560936951062
end methodA threadName=A--endTime:1560936954062

代碼作以下修改:

package chapter2.synch.method;

public class ThreadA extends Thread{
    
    private MyObject myObject;
    
    private Object object;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public MyObject getMyObject() {
        return myObject;
    }

    public void setMyObject(MyObject myObject) {
        this.myObject = myObject;
    }
    
    @Override
    public void run() {
        super.run();
        myObject.methodF(object);
    }

}

package chapter2.synch.method;

public class Run {

    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        Object object = new Object();
        ThreadA threadA = new ThreadA();
        threadA.setObject(object);
        threadA.setMyObject(myObject);
        threadA.setName("A");
        
        ThreadA threadB = new ThreadA();
        threadB.setMyObject(myObject);
        threadB.setObject(object);
        threadB.setName("B");
        
        threadA.start();
        threadB.start();
        
    }
}

運行結果:(同步執行)

begin methodF threadName=A--beginTime:1560937583035
end methodF threadName=A--endTime:1560937585035
begin methodF threadName=B--beginTime:1560937585035
end methodF threadName=B--endTime:1560937587035

結論:對象鎖。

若是synchronized加到static方法上是給Class類上鎖,Class鎖能夠對類的全部實例對象起做用。

特色:

  • synchronized關鍵字擁有鎖重入的功能,當一個線程獲得一個對象鎖後,再次請求此對象鎖時是能夠再次獲得該對象鎖的,不然就死鎖了。
  • 當存在父子繼承關係時,子類是能夠經過「可重入鎖」調用父類的同步方法的。
  • 出現異常,鎖自動釋放。
  • 同步不具備繼承性。
相關文章
相關標籤/搜索