標籤:open ref form 操作 lin 單位 div 參考 family
0、概述
synchronized是Java提供的內建的鎖機制,來實現代對碼塊的同步訪問,稱為內建鎖(Intrinsic Lock) 。內建鎖包括兩部分:一個是作為鎖的對象的引用,另一個是由這個鎖保護的代碼塊。需要理解的是,synchronized的鎖都是對象的引用,同一個對象只有一個內建鎖,不同的對象有不同的內建鎖。
Java 的內建鎖是一種互斥鎖,即一個對象的鎖只能同時被一個線程持有。假設線程A嘗試擷取線程B持有的鎖,線程A會被阻塞,知道B釋放該鎖,A才能持有該鎖。如果線程B永遠不是釋放該鎖,線程A也將永遠等待下去,形成死結。 由於線程在等待內建鎖的過程中無法被中斷,這是synchronized內建鎖的一個弊端,該需求可以被顯示鎖ReentranLock解決,可以參考這篇部落格:http://www.cnblogs.com/moongeek/p/7857794.html。
獲得一個對象內建鎖的唯一途徑就是進入由該對象鎖保護的代碼塊,釋放鎖的唯一途徑是跳出該代碼塊。一般synchronized使用方法如下:
synchronized(lock){ // 訪問或修改由該鎖保護的共用狀態}1、synchronized的使用
synchronized可以修飾一般方法、static方法、代碼塊,但是不論synchronized修飾什麼,他擷取的都是一個對象的內建鎖,鎖的單位都是對象。
1)synchronized 修飾一般方法,鎖是持有該方法的對象的鎖,訪問同一個類的相同方法時候會互斥。
public synchronized void doSomething(){ // ...}
上代碼等價於:
public void doSomething(){ synchronized(this){ // ... }}
2)synchronized 修飾代碼塊,鎖是指定的對象的鎖,如果是同一個對象的鎖,那麼會互斥訪問。
// 鎖為object對象的鎖synchronized(object){ }
3)synchronized 修飾靜態方法,鎖是該類Class對象的鎖,該類的所有對象訪問該類時都會互斥。
public class Demo{ public synchronized static void doSomething(){ // ... }}
上代碼等價於:
public class Demo{ public static void doSomething(){ synchronized(Demo.class){ // ... } }} 2、可重新進入性
當某個線程請求一個已經被其他線程持有的鎖時,該線程會被阻塞。但是內建鎖是可重新進入的,因此,如果一個內建鎖嘗試獲得已經由他自己持有的鎖,那這個請求會立即成功。“重入”意味著擷取鎖的操作粒度是“線程”而不是”調用“。
重入的實現方法是,為每個所關聯一個鎖和一個計數值。當計數值為0時,這個鎖就被認為是沒有被任何線程持有。當線程請求一個未被持有的線程時,JVM記下這個持有人,並且將計數值增1.如果同一個線程再次獲得這個鎖,計數值將增加,而當線程退出同步代碼塊時,計數器相應的遞減。當計數值為0,這個鎖將被釋放。
1 public class Test { 2 private Object lock; 3 4 public synchronized void saySomething(){ 5 6 } 7 8 public synchronized void doSomething(){ 9 // 兩個函數都是同一個對象鎖,可重新進入10 saySomething();11 }12 13 public void goSomewhere(){14 // 對象鎖不一致,不能重入15 synchronized (lock){16 saySomething();17 }18 }19 }
Java多線程學習之synchronized總結