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