synchronized 是屬於宣告式加鎖,可以修飾乙個**塊、乙個方法、乙個類,乙個靜態方法。
// 修飾乙個**塊
public
void
test1
(int j)
- {}"
, j, i);}
}}
// 修飾乙個方法
public
synchronized
void
test2
(int j)
- {}"
, j, i);}
}
// 修飾乙個類
public
static
void
test1
(int j)
- {}"
, j, i);}
}}
// 修飾乙個靜態方法
public
static
synchronized
void
test2
(int j)
- {}"
, j, i);}
}
synchronized 是在jvm層面實現的,不但可以通過一些監控工具監控,而且出現系統異常了,jvm也會自動的解鎖,所以jvm會自動的做加鎖與解鎖操作,其用法對開發人員是完全透明的。
reentrantlock 是物件層面的鎖,需要手動的加鎖和解鎖。在加解鎖時機有了更靈活的選擇,並且提供了公平選擇和非公平選擇。
// 請求總數
public
static
int clienttotal =
5000
;// 同時併發執行的執行緒數
public
static
int threadtotal =
200;
public
static
int count =0;
private
final
static lock lock =
newreentrantlock()
;public
static
void
main
(string[
] args)
throws exception
catch
(exception e)
countdownlatch.
countdown()
;});
} countdownlatch.
await()
; executorservice.
shutdown()
; log.
info
("count:{}"
, count);}
private
static
void
add(
)finally
}
reentrantreadwritelock 實現了readwritelock介面,所有具備讀、寫鎖。
我們在對外提供api介面時,如果要保證執行緒安全,則需要對訪問物件的讀寫進行加鎖,對同乙個物件加鎖。
但是,如果都操作的併發遠遠高於寫操作,那麼會出現寫操作的執行緒一直處於等待(讀操作釋放鎖)狀態。
讀寫鎖雖然分離了讀和寫的功能,使得讀與讀之間可以完全併發,但是讀和寫之間依然是衝突的,讀鎖會完全阻塞寫鎖,它使用的依然是悲觀的鎖策略.如果有大量的讀執行緒,他也有可能引起寫執行緒的飢餓
private
final map
map =
newtreemap
<
>()
;private
final reentrantreadwritelock lock =
newreentrantreadwritelock()
;private
final lock readlock = lock.
readlock()
;private
final lock writelock = lock.
writelock()
;public data get
(string key)
finally
}public set
getallkeys()
finally
}public data put
(string key, data value)
finally
}class
data
stampedlock則是1.8後提供了一種樂觀的讀策略,這種樂觀策略的鎖非常類似於無鎖的操作,使得樂觀鎖完全不會阻塞寫執行緒;
內部實現是基於clh鎖的,clh鎖是一種自旋鎖,它保證沒有飢餓的發生,並且可以保證fifo(先進先出)的服務順序.
clh鎖的基本思想如下:鎖維護乙個等待執行緒佇列,所有申請鎖,但是沒有成功的執行緒都記錄在這個佇列中,每乙個節點代表乙個執行緒,儲存乙個標記位(locked).用與判斷當前執行緒是否已經釋放鎖;locked=true 沒有獲取到鎖,false 已經成功釋放了鎖
// 請求總數
public
static
int clienttotal =
5000
;// 同時併發執行的執行緒數
public
static
int threadtotal =
200;
public
static
int count =0;
private
final
static stampedlock lock =
newstampedlock()
;public
static
void
main
(string[
] args)
throws exception
catch
(exception e)
countdownlatch.
countdown()
;});
} countdownlatch.
await()
; executorservice.
shutdown()
; log.
info
("count:{}"
, count);}
private
static
void
add(
)finally
}
原始碼案例
class
point
finally
}//下面看看樂觀讀鎖案例
double
distancefromorigin()
finally
}return math.
sqrt
(currentx * currentx + currenty * currenty);}
//下面是悲觀讀鎖案例
void
moveifatorigin
(double newx,
double newy)
else}}
finally
}}
1、當併發量不是特別的時候,synchronized 是比較好的選擇,並且是不會引起死鎖的。
2、併發量不少,但執行緒數是可以預估的,reentrantlock是乙個比較好的實現。
Java併發之讀 寫鎖
讀取 沒有執行緒正在做寫操作且沒有執行緒請求寫操作 寫入 沒有執行緒正在做寫操作 這裡假設寫操作的優先順序比讀操作高 當乙個執行緒已經擁有寫鎖,才允許寫鎖重入 public class readwritelock writerequest writeaccesses writingthread ca...
Java併發之公平鎖
cpu在排程執行緒的時候,會在等待佇列裡隨機挑選乙個執行緒。由於隨機性,故不能保證執行緒先到先得 synchronized控制的鎖就是這種非公平鎖 這樣就會產生飢餓現象,即有些優先順序較低的執行緒可能永遠無法取得cpu的執行權,優先順序較高的執行緒會不斷搶占資源。於是,就有了公平鎖。公平鎖可以保證執...
高併發和鎖
面試被問到了這個問題,找了答案,記錄一下 假如有100w個使用者,搶一張票,除了負載均衡的辦法,怎麼支援高併發?修改字段 將庫存欄位number欄位設為unsigned,當庫存為0時,因為字段不能為負數,將會返回false 利用悲觀鎖 不適合高併發 悲觀鎖,也就是在修改資料的時候,採用鎖定狀態,排斥...