介紹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鎖能夠對類的全部實例對象起做用。
特色: