最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中提供synchronized后為什么還要提供Lock

 更新時間:2022年03月30日 16:37:19   作者:冰?河?  
這篇文章主要介紹了Java中提供synchronized后為什么還要提供Lock,在Java中提供了synchronized關鍵字來保證只有一個線程能夠訪問同步代碼塊,下文更多相關資料需要的小伙伴可以參考一下

 摘要: 在Java中提供了synchronized關鍵字來保證只有一個線程能夠訪問同步代碼塊。既然已經提供了synchronized關鍵字,那為何在Java的SDK包中,還會提供Lock接口呢?這是不是重復造輪子,多此一舉呢?今天,我們就一起來探討下這個問題。

在Java中提供了synchronized關鍵字來保證只有一個線程能夠訪問同步代碼塊。既然已經提供了synchronized關鍵字,那為何在Java的SDK包中,還會提供Lock接口呢?這是不是重復造輪子,多此一舉呢?今天,我們就一起來探討下這個問題。

問題?

既然JVM中提供了synchronized關鍵字來保證只有一個線程能夠訪問同步代碼塊,為何還要提供Lock接口呢?這是在重復造輪子嗎?Java的設計者們?yōu)楹我@樣做呢?讓我們一起帶著疑問往下看。

一、為何提供Lock接口?

很多小伙伴可能會聽說過,在Java 1.5版本中,synchronized的性能不如Lock,但在Java 1.6版本之后,synchronized做了很多優(yōu)化,性能提升了不少。那既然synchronized關鍵字的性能已經提升了,那為何還要使用Lock呢?

如果我們向更深層次思考的話,就不難想到了:我們使用synchronized加鎖是無法主動釋放鎖的,這就會涉及到死鎖的問題。

二、死鎖問題

如果要發(fā)生死鎖,則必須存在以下四個必要條件,四者缺一不可。

  • 互斥條件

在一段時間內某資源僅為一個線程所占有。此時若有其他線程請求該資源,則請求線程只能等待。

  • 不可剝奪條件

線程所獲得的資源在未使用完畢之前,不能被其他線程強行奪走,即只能由獲得該資源的線程自己來釋放(只能是主動釋放)。

  • 請求與保持條件

線程已經保持了至少一個資源,但又提出了新的資源請求,而該資源已被其他線程占有,此時請求線程被阻塞,但對自己已獲得的資源保持不放。

  • 循環(huán)等待條件

在發(fā)生死鎖時必然存在一個進程等待隊列{P1,P2,…,Pn},其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個進程等待環(huán)路,環(huán)路中每一個進程所占有的資源同時被另一個申請,也就是前一個進程占有后一個進程所深情地資源。

三、synchronized的局限性

如果我們的程序使用synchronized關鍵字發(fā)生了死鎖時,synchronized關鍵是是無法破壞“不可剝奪”這個死鎖的條件的。這是因為synchronized申請資源的時候, 如果申請不到, 線程直接進入阻塞狀態(tài)了, 而線程進入阻塞狀態(tài), 啥都干不了, 也釋放不了線程已經占有的資源。

然而,在大部分場景下,我們都是希望“不可剝奪”這個條件能夠被破壞。也就是說對于“不可剝奪”這個條件,占用部分資源的線程進一步申請其他資源時, 如果申請不到, 可以主動釋放它占有的資源, 這樣不可剝奪這個條件就破壞掉了。

如果我們自己重新設計鎖來解決synchronized的問題,我們該如何設計呢?

四、解決問題

了解了synchronized的局限性之后,如果是讓我們自己實現(xiàn)一把同步鎖,我們該如何設計呢?也就是說,我們在設計鎖的時候,要如何解決synchronized的局限性問題呢?這里,我覺得可以從三個方面來思考這個問題。

(1)能夠響應中斷。 synchronized的問題是, 持有鎖A后, 如果嘗試獲取鎖B失敗, 那么線程就進入阻塞狀態(tài), 一旦發(fā)生死鎖, 就沒有任何機會來喚醒阻塞的線程。 但如果阻塞狀態(tài)的線程能夠響應中斷信號, 也就是說當我們給阻塞的線程發(fā)送中斷信號的時候, 能夠喚醒它, 那它就有機會釋放曾經持有的鎖A。 這樣就破壞了不可剝奪條件了。

(2)支持超時。 如果線程在一段時間之內沒有獲取到鎖, 不是進入阻塞狀態(tài), 而是返回一個錯誤, 那這個線程也有機會釋放曾經持有的鎖。 這樣也能破壞不可剝奪條件。

(3)非阻塞地獲取鎖。 如果嘗試獲取鎖失敗, 并不進入阻塞狀態(tài), 而是直接返回, 那這個線程也有機會釋放曾經持有的鎖。 這樣也能破壞不可剝奪條件。

體現(xiàn)在Lock接口上,就是Lock接口提供的三個方法,

如下所示:

// 支持中斷的API
void lockInterruptibly() throws InterruptedException;
// 支持超時的API
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 支持非阻塞獲取鎖的API
boolean tryLock();
  • lockInterruptibly()

支持中斷。

  • tryLock()方法

tryLock()方法是有返回值的,它表示用來嘗試獲取鎖,如果獲取成功,則返回true,如果獲取失?。存i已被其他線程獲?。瑒t返回false,也就說這個方法無論如何都會立即返回。在拿不到鎖時不會一直在那等待。

  • tryLock(long time, TimeUnit unit)方法

tryLock(long time, TimeUnit unit)方法和tryLock()方法是類似的,只不過區(qū)別在于這個方法在拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false。如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true。

也就是說,對于死鎖問題,Lock能夠破壞不可剝奪的條件,例如,我們下面的程序代碼就破壞了死鎖的不可剝奪的條件。

public class TansferAccount{
    private Lock thisLock = new ReentrantLock();
    private Lock targetLock = new ReentrantLock();
    //賬戶的余額
    private Integer balance;
    //轉賬操作
    public void transfer(TansferAccount target, Integer transferMoney){
        boolean isThisLock = thisLock.tryLock();
        if(isThisLock){
            try{
                boolean isTargetLock = targetLock.tryLock();
                if(isTargetLock){
                    try{
                         if(this.balance >= transferMoney){
                            this.balance -= transferMoney;
                            target.balance += transferMoney;
                        }   
                    }finally{
                        targetLock.unlock
                    }
                }
            }finally{
                thisLock.unlock();
            }
        }
    }
}

例外,Lock下面有一個ReentrantLock,而ReentrantLock支持公平鎖和非公平鎖。

在使用ReentrantLock的時候, ReentrantLock中有兩個構造函數(shù), 一個是無參構造函數(shù), 一個是傳入fair參數(shù)的構造函數(shù)。 fair參數(shù)代表的是鎖的公平策略, 如果傳入true就表示需要構造一個公平鎖, 反之則表示要構造一個非公平鎖。如下代碼片段所示。

//無參構造函數(shù): 默認非公平鎖
public ReentrantLock() {
	sync = new NonfairSync();
} 
//根據(jù)公平策略參數(shù)創(chuàng)建鎖
public ReentrantLock(boolean fair){
	sync = fair ? new FairSync() : new NonfairSync();
}

鎖的實現(xiàn)在本質上都對應著一個入口等待隊列, 如果一個線程沒有獲得鎖, 就會進入等待隊列, 當有線程釋放鎖的時候, 就需要從等待隊列中喚醒一個等待的線程。 如果是公平鎖, 喚醒的策略就是誰等待的時間長, 就喚醒誰, 很公平; 如果是非公平鎖, 則不提供這個公平保證, 有可能等待時間短的線程反而先被喚醒。 而Lock是支持公平鎖的,synchronized不支持公平鎖。

最后,值得注意的是,在使用Lock加鎖時,一定要在finally{}代碼塊中釋放鎖,例如,下面的代碼片段所示。

try{
    lock.lock();
}finally{
    lock.unlock();
}

注:其他synchronized和Lock的詳細說明,小伙伴們自行查閱即可。

到此這篇關于Java中提供synchronized后為什么還要提供Lock的文章就介紹到這了,更多相關Java中 synchronized  Lock內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Springboot項目中單元測試時注入bean失敗的解決方案

    Springboot項目中單元測試時注入bean失敗的解決方案

    這篇文章主要介紹了Springboot項目中單元測試時注入bean失敗的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 詳解rabbitmq使用springboot實現(xiàn)fanout模式

    詳解rabbitmq使用springboot實現(xiàn)fanout模式

    這篇文章主要介紹了rabbitmq使用springboot實現(xiàn)fanout模式,Fanout特點是發(fā)布與訂閱模式,是一種廣播機制,它是沒有路由key的模式,需要的朋友可以參考下
    2023-07-07
  • Spring Boot如何優(yōu)化內嵌的Tomcat示例詳解

    Spring Boot如何優(yōu)化內嵌的Tomcat示例詳解

    spring boot默認web程序啟用tomcat內嵌容器,監(jiān)聽8080端口,下面這篇文章主要給大家介紹了關于Spring Boot如何優(yōu)化內嵌Tomcat的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • 你的Idea還有BUG嗎不妨試試另一個開發(fā)神器

    你的Idea還有BUG嗎不妨試試另一個開發(fā)神器

    Spring Tool Suite(STS)就是一個基于Eclipse的開發(fā)環(huán)境, 用于開發(fā)Spring應用程序。本文給大家給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-12-12
  • Spring中如何動態(tài)注入Bean實例教程

    Spring中如何動態(tài)注入Bean實例教程

    這篇文章主要給大家介紹了關于Spring中如何動態(tài)注入Bean的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-12-12
  • 淺析Java中并發(fā)工具類的使用

    淺析Java中并發(fā)工具類的使用

    在JDK的并發(fā)包里提供了幾個非常有用的并發(fā)工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種并發(fā)流程控制的手段,Exchanger工具類提供了在線程間交換數(shù)據(jù)的一種方法。本文主要介紹了它們的使用,需要的可以參考一下
    2022-12-12
  • Java實現(xiàn)簡單修改文件名的方法分析

    Java實現(xiàn)簡單修改文件名的方法分析

    這篇文章主要介紹了Java實現(xiàn)簡單修改文件名的方法,結合具體實例分析了2種比較常用的java文件名修改方法,需要的朋友可以參考下
    2017-09-09
  • Java實現(xiàn)FIFO功能的完整代碼實踐

    Java實現(xiàn)FIFO功能的完整代碼實踐

    在軟件開發(fā)中,隊列(Queue)是一種常見的數(shù)據(jù)結構,其特點是先進先出(FIFO,First In First Out),FIFO 隊列在生產者-消費者模型、任務調度、緩沖區(qū)管理等場景中具有廣泛的應用,本文給大家介紹了Java實現(xiàn)FIFO功能的完整代碼實踐,需要的朋友可以參考下
    2025-03-03
  • import java和javax區(qū)別小結

    import java和javax區(qū)別小結

    Java包和javax包在Java編程語言中都起著至關重要的作用,本文就來介紹一下import java和javax區(qū)別小結,具有一定的參考價值,感興趣的可以了解一下
    2024-10-10
  • SpringBoot實現(xiàn)網站的登陸注冊邏輯記錄

    SpringBoot實現(xiàn)網站的登陸注冊邏輯記錄

    登陸注冊功能是我們日常開發(fā)中經常遇到的一個功能,下面這篇文章主要給大家介紹了關于SpringBoot實現(xiàn)網站的登陸注冊邏輯的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-10-10

最新評論

石台县| 汤阴县| 潼关县| 大安市| 左权县| 苗栗市| 桂平市| 象山县| 弋阳县| 株洲市| 卢龙县| 呼玛县| 鲜城| 太康县| 镇安县| 阿坝县| 渭源县| 通许县| 酒泉市| 松原市| 宁波市| 肇东市| 凤阳县| 阳高县| 柏乡县| 基隆市| 玉屏| 石泉县| 清新县| 伊川县| 四子王旗| 台安县| 忻州市| 博罗县| 罗山县| 洛南县| 常熟市| 清镇市| 滦南县| 旌德县| 广德县|