synchronized能夠修飾代碼塊也能夠修飾方法,還能夠做用於靜態方法,類和某個實例。java
每一個對象都有一把鎖,當多個線程同時訪問共享資源的時候,須要用到synchronized,synchronized分爲代碼塊和方法,代碼塊須要顯示的指定對象,而方法不須要(即當前對象)。ide
java的內存模型是對每個進程都有主內存,每一個線程也有本身的內存,它們從主內存中取數據,而後在計算,在存入主內存。函數
例子:如今有兩個線程A,B線程,A線程對變量i加1,B線程同時對i加2,這兩個線程同時操做,若是沒有同步處理則B線程作的操做會覆蓋A線程的操做。this
這時能夠用synchronized處理,synchronized具備原子性,原子操做:取數據,操做數據,存數據。synchronized能夠保證同一時間只有一個線程操做該對象。spa
java中對非Long和Float原始數據類型的存,取爲原子操做。其實就是對一個字節的存,取操做,因爲Float和Long爲兩個字節,因此其取,存爲非原子操做。若是想把他們變成原子操做能夠用volatile.線程
做用區域主要有兩種:code
(1)、方法對象
(2)、代碼塊進程
對於用一對像的同步操做只能有一個線程,而對於不一樣對象是互不干擾的。
內存
Public synchronized void change() { //同步方法 } Public void change() { Synchronized(this) { //同步語句:(由於效率問題,有時考慮使用同步語句塊) } }
同步方法是針對當前對象的,若是不針對當前對象,而是針對其餘對象能夠用同步語句,如:
private byte[] lock= new byte[0]; Public void change() { Synchronized(lock) { } }
自定義鎖注意:
a、對象必須爲private防止其餘類對象訪問
b、geter方法最好clone一個對象返回
其餘用法
能夠針對靜態方法和類
Class Foo { public synchronizedstatic void methodAAA()// 同步的static 函數 { //…. } public void methodBBB() { synchronized(Foo.class) // class literal(類名稱字面常量) } }
它是針對整個類的,因此只能是同一個類的一個線程進行訪問
synchronized(this)與synchronized(static class)的區別:
synchronized就是針對內存區塊申請內存鎖,this是類的一個對象,也就是針對相同對象的互斥操做,其餘線程能夠訪問該類的其餘對象。static是針對類,static是整個類共有的,也就是該類的全部成員間互斥。在同一時間只有一個線程能夠訪問該類的實例。
創建三個線程,A線程打印10次A,B線程打印10次B,C線程打印10次C,要求線程同時運行,交替打印10次ABC。這個問題用Object的wait(),notify()就能夠很方便的解決。代碼以下:
public class MyThreadPrinter2 implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter2(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; while (count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); new Thread(pa).start(); new Thread(pb).start(); new Thread(pc).start(); } }