摘要:了解自動(dòng)鎖很早就受不了鎖的機(jī)制了每次都需要在去解鎖不僅代碼不美觀而且很麻煩我想能不能實(shí)現(xiàn)加鎖之后自動(dòng)解鎖如果是可以利用析構(gòu)函數(shù)實(shí)現(xiàn)但就想了想好像可以利用的特性對(duì)象只需要實(shí)現(xiàn)接口實(shí)現(xiàn)自動(dòng)鎖我了解如何利用特性寫(xiě)一個(gè)自動(dòng)鎖那么下面我們開(kāi)始真正
了解自動(dòng)鎖
很早就受不了 java 鎖的機(jī)制了,每次都需要在 finally 去解鎖, 不僅代碼不美觀,而且很麻煩
我想能不能實(shí)現(xiàn)加鎖之后自動(dòng)解鎖, 如果是C++ 可以利用析構(gòu)函數(shù)實(shí)現(xiàn), 但java就.......
想了想好像可以利用java7 的 try-with-resource 特性, 對(duì)象只需要實(shí)現(xiàn) AutoCloseable 接口
class AutoLock implements AutoCloseable { // other function start // ........ // other function end // I like this feature @Override public void close() throws Exception { unLock(); } }
實(shí)現(xiàn)自動(dòng)鎖
我了解如何利用java特性寫(xiě)一個(gè)自動(dòng)鎖那么, 下面我們開(kāi)始真正的實(shí)現(xiàn)
// 自動(dòng)鎖實(shí)現(xiàn)類 public static class AutoLock implements AutoCloseable { // 重入鎖對(duì)象 private ReentrantLock reentrantLock = new ReentrantLock(); /** * 自動(dòng)鎖 加鎖 * @return 返回自動(dòng)鎖本身 */ public AutoLock lock() { // 加鎖 reentrantLock.lock(); return this; } public static AutoLock getAutoLock() { return new AutoLock().lock(); } /** * 自動(dòng)鎖解鎖 * @return 返回自動(dòng)鎖本身 */ private AutoLock unLock() { // 解鎖 if (null != reentrantLock && reentrantLock.isLocked()) { reentrantLock.unlock(); } return this; } @Override public void close() throws Exception { unLock(); } }
// 簡(jiǎn)單, 調(diào)用示例 public void testAutoLock() throws Exception { try(AutoLock autoLock = new AutoLock()) { autoLock.lock() // do some thing..... } // 不用再解鎖了, 不用再解鎖了, 不用再解鎖了!!! }
// 更方便的調(diào)用示例 public void testAutoLock() throws Exception { // 使用靜態(tài)方法 try(AutoLock autoLock = AutoLock.getAutoLock()) { // do some thing..... } // 不用再解鎖了, 不用再解鎖了, 不用再解鎖了!!! }
自動(dòng)鎖的使用場(chǎng)景
前面兩種調(diào)用方式, 只是打個(gè)比方, 但是很多時(shí)候,我們的需求并不是 每次都需要 new ReentrantLock(), 這樣并沒(méi)有什么N用的, 因?yàn)槊看涡碌?重入鎖"實(shí)例, 起不到防止重入的目的, 那我們改變一下方式, 我們做兩個(gè)地方的改變, 我們修改reentrantLock 成員不做初始化new, 而是通過(guò)參數(shù)傳入Lock 抽象接口對(duì)象
// 自動(dòng)鎖實(shí)現(xiàn)類 public class AutoLock implements AutoCloseable { // *重入鎖對(duì)象 (改變1)* private Lock autoLock = null // *重寫(xiě)構(gòu)造函數(shù)(改變2)* private AutoLock(Lock autoLock) { this.autoLock = autoLock; } /** * 自動(dòng)鎖 加鎖 * @return 返回自動(dòng)鎖本身 */ public AutoLock lock() { // *加鎖(改變3)* if (null != reentrantLock) { reentrantLock.lock(); } return this; } // *獲取自動(dòng)鎖對(duì)象 (改變4)* public static AutoLock getAutoLock(Lock autoLock) { return new AutoLock(autoLock).lock(); } /** * 自動(dòng)鎖解鎖 * @return 返回自動(dòng)鎖本身 */ private AutoLock unLock() { // 解鎖 if (null != autoLock) { autoLock.unlock(); } return this; } @Override public void close() throws Exception { unLock(); } }
至于為什么傳入的是 Lock 抽象接口, 因?yàn)楹芩鶗r(shí)候,我們可能自定義一個(gè)鎖對(duì)象, 或者以后JDK可能提供的其他鎖, 我們來(lái)看看調(diào)用示例吧
public class TestService() { private Lock reentrantLock = new ReentrantLock(); // 假設(shè)線程A調(diào)用此方法 pubilc void testAutoLockA() throws Exception { try(AutoLock autoLock = AutoLock.getAutoLock(reentrantLock)) { // do some thing.... } } // 假設(shè)線程B調(diào)用此方法 public void testAutoKLockB() throws Exception { try(AutoLock autoLock = AutoLock.getAutoLock(reentrantLock)) { // do some thing.... } } }
至此我們就實(shí)現(xiàn)了,我們假設(shè)的常用場(chǎng)景
更高級(jí)的用法
如果我要更細(xì)粒度的鎖, 不是在對(duì)象的成員中存在鎖對(duì)象,怎么辦.
我寫(xiě)一個(gè)方法, 希望可以幫助大家, 拋磚引玉, 如果可以提供更好的方式請(qǐng)求留言
/** * Description: TestLock * Created by: IcerLeer * Created on: 2017-08-31 17:42 */ public class LockUtils { // 自動(dòng)鎖緩存隊(duì)列, 實(shí)現(xiàn)不可重入 private static ConcurrentHashMaplockMap = new ConcurrentHashMap<>(); /** * 獲取自動(dòng)鎖 * @param strKey 自動(dòng)鎖關(guān)鍵字 * @return 返回自動(dòng)鎖對(duì)象 */ public static AutoLock getAutoLock(String strKey) { synchronized (strKey.intern()) { return lockMap.computeIfAbsent(strKey, key -> new AutoLock(strKey)).lock(); } } /** * 移除自動(dòng)鎖 * @param strKey 自動(dòng)鎖關(guān)鍵字 */ private static void removeAutoLock(String strKey) { lockMap.remove(strKey); } /** * 自動(dòng)鎖 */ public static class AutoLock implements AutoCloseable { // 鎖的關(guān)鍵字 private String lockKey = ""; // 事務(wù)鎖對(duì)象 private ReentrantLock reentrantLock = new ReentrantLock(); // 引用計(jì)數(shù) private int refNumber = 0; // 初始化構(gòu)造函數(shù) public AutoLock(String strKey) { if (StringUtils.isNotBlank(strKey)) { lockKey = strKey; } } /** * 自動(dòng)鎖 加鎖 * @return 返回自動(dòng)鎖本身 */ private AutoLock lock() { // 增加引用次數(shù) refNumber++; // 加鎖 reentrantLock.lock(); return this; } /** * 自動(dòng)鎖解鎖 * @return 返回自動(dòng)鎖本身 */ private AutoLock unLock() { // 解鎖 if (null != reentrantLock && reentrantLock.isLocked()) { reentrantLock.unlock(); // 判斷是否應(yīng)該把自動(dòng)鎖移除隊(duì)列 synchronized (lockKey.intern()) { // 減少引用次數(shù) refNumber--; // 如果引用計(jì)數(shù) if (0 == refNumber) { removeAutoLock(lockKey); } } } return this; } @Override public void close() throws Exception { unLock(); } } }
當(dāng)然少不了調(diào)用示例
private void testAutoLockA() throws Exception { /// "Test" 為鎖的關(guān)鍵字, 相同的關(guān)鍵字實(shí)現(xiàn)不可重入鎖 try(LockUtils.AutoLock autoLock = LockUtils.getAutoLock("Test")) { // do some thing sleep(10); } } private void testAutoLockB() throws Exception { /// "Test" 為鎖的關(guān)鍵字, 相同的關(guān)鍵字實(shí)現(xiàn)不可重入鎖 try(LockUtils.AutoLock autoLock = LockUtils.getAutoLock("Test")) { // do some thing sleep(10); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70306.html
摘要:簡(jiǎn)介是的線程安全版本,內(nèi)部也是使用數(shù)組鏈表紅黑樹(shù)的結(jié)構(gòu)來(lái)存儲(chǔ)元素。相比于同樣線程安全的來(lái)說(shuō),效率等各方面都有極大地提高。中的關(guān)鍵字,內(nèi)部實(shí)現(xiàn)為監(jiān)視器鎖,主要是通過(guò)對(duì)象監(jiān)視器在對(duì)象頭中的字段來(lái)表明的。 簡(jiǎn)介 ConcurrentHashMap是HashMap的線程安全版本,內(nèi)部也是使用(數(shù)組 + 鏈表 + 紅黑樹(shù))的結(jié)構(gòu)來(lái)存儲(chǔ)元素。 相比于同樣線程安全的HashTable來(lái)說(shuō),效率等各方...
摘要:并發(fā)編程導(dǎo)論是對(duì)于分布式計(jì)算并發(fā)編程系列的總結(jié)與歸納。并發(fā)編程導(dǎo)論隨著硬件性能的迅猛發(fā)展與大數(shù)據(jù)時(shí)代的來(lái)臨,并發(fā)編程日益成為編程中不可忽略的重要組成部分。并發(fā)編程復(fù)興的主要驅(qū)動(dòng)力來(lái)自于所謂的多核危機(jī)。 并發(fā)編程導(dǎo)論是對(duì)于分布式計(jì)算-并發(fā)編程 https://url.wx-coder.cn/Yagu8 系列的總結(jié)與歸納。歡迎關(guān)注公眾號(hào):某熊的技術(shù)之路。 showImg(https://...
閱讀 1740·2021-11-25 09:43
閱讀 1785·2021-11-24 10:41
閱讀 3105·2021-09-27 13:36
閱讀 811·2019-08-30 15:53
閱讀 3567·2019-08-30 15:44
閱讀 866·2019-08-30 14:03
閱讀 2572·2019-08-29 16:38
閱讀 996·2019-08-29 13:23