亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中線程安全問(wèn)題

 更新時(shí)間:2021年05月11日 11:02:05   作者:IT BOY  
這篇文章主要介紹了Java中線程安全問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一.線程不安全

多線程的執(zhí)行環(huán)境中,程序的執(zhí)行結(jié)果和預(yù)期的結(jié)果不符合,這就稱為發(fā)生了線程不安全現(xiàn)象

二.那些情況導(dǎo)致了線程不安全?

大致分為以下5種情況:

(1)CPU搶占執(zhí)行 (無(wú)法解決);
(2)非原子性 ;
(3)編譯器優(yōu)化(指令重排) 編譯器優(yōu)化在單線程下執(zhí)行沒(méi)問(wèn)題,多線程下優(yōu)化會(huì)發(fā)生混亂;
(4)內(nèi)存的不可見(jiàn)性 ;(volatile輕量級(jí)解決)
(5)多個(gè)線程修改了同一個(gè)變量。(方案:讓線程操作自己的變量可以解決該問(wèn)題,但業(yè)務(wù)場(chǎng)景發(fā)生變化,修改難度變大,通用性不高)

三.Java中解決線程不安全的方案

1.volatile“輕量級(jí)”解決線程不安全

在這里插入圖片描述

volatile的出現(xiàn)可以解決上圖所展現(xiàn)的內(nèi)存不可見(jiàn)問(wèn)題以及禁止指令重排

實(shí)現(xiàn)原理:工作內(nèi)存中的變量操作結(jié)束后,強(qiáng)制刪除線程工作內(nèi)存中的變量,起到內(nèi)存可見(jiàn)注意事項(xiàng):volatile不能解決原子性問(wèn)題。volatile可以解決線程不安全問(wèn)題是錯(cuò)誤的(說(shuō)法不夠嚴(yán)謹(jǐn))

下面兩種方案通過(guò)對(duì)關(guān)鍵代碼加鎖,讓cpu排隊(duì)執(zhí)行,鎖操作的步驟為:
1)嘗試獲取鎖,如果拿到則加鎖,否則排隊(duì)等待獲取鎖  2)釋放鎖操作

2.synchronized自動(dòng)加鎖

①synchronized進(jìn)行自動(dòng)加鎖和釋放鎖,是Jvm層面的解決方案

synchronized使用舉例:使用兩個(gè)線程對(duì)變量count進(jìn)行一次++ 和 一次- -

在這里插入圖片描述

沒(méi)有使用synchronized上鎖之前,由于非原子問(wèn)題,兩個(gè)線程進(jìn)行++和- -出現(xiàn)線程不安全問(wèn)題,通過(guò)synchronized關(guān)鍵字的使用,解決了非原子問(wèn)題,代碼運(yùn)行實(shí)際結(jié)果和預(yù)期結(jié)果一致,保證了線程安全。

②synchronized實(shí)現(xiàn)原理:

1.基于操作系統(tǒng)而言,通過(guò)互斥鎖mutex實(shí)現(xiàn)
2.從Jvm層面來(lái)看,實(shí)現(xiàn)了一個(gè)監(jiān)視器鎖的加鎖和釋放鎖過(guò)程。
在這里插入圖片描述
3.從Java語(yǔ)言本身來(lái)看,存在一個(gè)互斥鎖mutex對(duì)象,鎖存在于對(duì)象的對(duì)象頭中,對(duì)象頭中的“偏向線程ID”,表明該鎖被該線程占有,釋放鎖后,偏向線程ID消失。

mutex結(jié)構(gòu)信息:
在這里插入圖片描述
Owner代表鎖的擁有者,為null時(shí)表示鎖未使用;Nest表示鎖的使用次數(shù),為0表示沒(méi)有被使用;此外鎖可以嵌套使用,不會(huì)發(fā)生死鎖情況。

③synchronized鎖升級(jí)過(guò)程:

沒(méi)有線程訪問(wèn)時(shí)處于無(wú)鎖狀態(tài) >> 第一個(gè)線程訪問(wèn)時(shí),由無(wú)鎖狀態(tài)轉(zhuǎn)為偏向鎖 >> 輕量級(jí)鎖(其他線程嘗試獲取鎖,鎖處于自旋狀態(tài)) >> 重量級(jí)鎖(把沒(méi)有拿到鎖的線程放到等待隊(duì)列里面)

3.Lock手動(dòng)上鎖

Lock需要程序員自己手動(dòng)上鎖手動(dòng)釋放鎖;Lock是一個(gè)interface;創(chuàng)建鎖時(shí)可以通過(guò)Lock的實(shí)現(xiàn)類ReentrantLock()完成:Lock lock = new ReentrantLock();加鎖操作lock.lock(),釋放鎖操作lock.unlock()

使用Lock需要注意的問(wèn)題:

一定要把加鎖操作lock()放在try/finally外面如果把lock()放在try中會(huì)導(dǎo)致兩個(gè)問(wèn)題發(fā)生:
(1)try中代碼出現(xiàn)異常,此時(shí)就會(huì)執(zhí)行finally中釋放鎖的操作,如果try還沒(méi)有加鎖就去釋放鎖,勢(shì)必是不行的。
(2)try中出現(xiàn)異常后,執(zhí)行finally中釋放鎖操作,線程狀態(tài)異常會(huì)將try中業(yè)務(wù)異常覆蓋掉,增加了排除錯(cuò)誤的成本。
在這里插入圖片描述
在這里插入圖片描述
將lock()放在try中第一句可以解決這個(gè)問(wèn)題
在這里插入圖片描述
在這里插入圖片描述
對(duì)比發(fā)現(xiàn),這樣做業(yè)務(wù)異常是不會(huì)被線程的狀態(tài)異常覆蓋的,方便了排查錯(cuò)誤?。。?

四.公平鎖與非公平鎖機(jī)制

公平鎖線程按順序執(zhí)行;非公平鎖沒(méi)有順序,執(zhí)行效率更高;Java中默認(rèn)鎖策略為非公平鎖機(jī)制synchronized鎖機(jī)制:采用非公平鎖機(jī)制Lock鎖機(jī)制:默認(rèn)采用非公平鎖機(jī)制,但是可以顯示地聲明為公平鎖,比如在創(chuàng)建鎖對(duì)象時(shí),在構(gòu)造方法中傳true:Lock lock = new ReentrantLock(true)

五.volatile和synchronized的區(qū)別

volatile可以解決內(nèi)存不可見(jiàn)問(wèn)題以及禁止指令重排序,但是不能解決非原子性問(wèn)題;
synchronized可以解決大部分線程的非安全問(wèn)題,保證關(guān)鍵代碼排隊(duì)執(zhí)行,無(wú)論何時(shí)鎖只被一個(gè)線程擁有,可解決非原子性問(wèn)題

六.synchronized和Lock的區(qū)別

1.synchronized自動(dòng)加鎖和釋放鎖,而Lock需要手動(dòng)加鎖和釋放鎖;

2.synchronized是Jvm層面的實(shí)現(xiàn),Lock是Java語(yǔ)言層面的實(shí)現(xiàn);

3.適用范圍不同:synchronized可以修飾代碼塊(對(duì)任意對(duì)象加鎖)、修飾靜態(tài)方法(對(duì)當(dāng)前的類進(jìn)行加鎖)、修飾普通的方法(對(duì)當(dāng)前的實(shí)例對(duì)象進(jìn)行加鎖);而Lock只能修飾代碼塊;

4.synchronized只有非公平鎖策略;Lock默認(rèn)采用非公平鎖機(jī)制,但可以顯示聲明為公平鎖;

5.Lock的靈活性更高一些(比如:tryLock)

到此這篇關(guān)于Java中線程安全問(wèn)題的文章就介紹到這了,更多相關(guān)Java線程安全內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SparkSQL使用快速入門(mén)

    SparkSQL使用快速入門(mén)

    spark SQL是spark的一個(gè)模塊,主要用于進(jìn)行結(jié)構(gòu)化數(shù)據(jù)的處理。它提供的最核心的編程抽象就是DataFrame。這篇文章主要介紹了SparkSQL使用快速入門(mén),需要的朋友可以參考下
    2021-08-08
  • Maven的pom.xml文件結(jié)構(gòu)中的build

    Maven的pom.xml文件結(jié)構(gòu)中的build

    本文主要介紹了Maven的pom.xml文件結(jié)構(gòu)中的build,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Java處理不可見(jiàn)特殊字符要點(diǎn)解析

    Java處理不可見(jiàn)特殊字符要點(diǎn)解析

    這篇文章主要介紹了Java處理不可見(jiàn)特殊字符要點(diǎn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 以Java代碼為例講解設(shè)計(jì)模式中的簡(jiǎn)單工廠模式

    以Java代碼為例講解設(shè)計(jì)模式中的簡(jiǎn)單工廠模式

    簡(jiǎn)單來(lái)說(shuō),工廠模式就是按照需求來(lái)返回一個(gè)類型的對(duì)象,使用工廠模式的意義就是,如果對(duì)象的實(shí)例化與代碼依賴太大的話,不方便進(jìn)行擴(kuò)展和維護(hù),使用工廠的目的就是使對(duì)象的實(shí)例化與主程序代碼就行解耦.來(lái)具體看一下:
    2016-05-05
  • idea插件開(kāi)發(fā)之彈出框的示例代碼

    idea插件開(kāi)發(fā)之彈出框的示例代碼

    這篇文章主要介紹了idea插件開(kāi)發(fā)之彈出框的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • springboot實(shí)現(xiàn)圖片大小壓縮功能

    springboot實(shí)現(xiàn)圖片大小壓縮功能

    這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)圖片大小壓縮功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳解Spring?中?Bean?對(duì)象的存儲(chǔ)和取出

    詳解Spring?中?Bean?對(duì)象的存儲(chǔ)和取出

    由于?Spring?擁有對(duì)象的管理權(quán),所以我們也需要擁有較為高效的對(duì)象存儲(chǔ)和取出的手段,下面我們來(lái)分別總結(jié)一下,對(duì)Spring?中?Bean?對(duì)象的存儲(chǔ)和取出知識(shí)感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • 攜程Apollo(阿波羅)安裝部署以及java整合實(shí)現(xiàn)

    攜程Apollo(阿波羅)安裝部署以及java整合實(shí)現(xiàn)

    這篇文章主要介紹了攜程Apollo(阿波羅)安裝部署以及java整合實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java8新特性:lambda表達(dá)式總結(jié)

    Java8新特性:lambda表達(dá)式總結(jié)

    這篇文章主要介紹了Java8新特性:lambda表達(dá)式總結(jié),本文總結(jié)了多種語(yǔ)法格式和使用方法,包含了函數(shù)式接口和內(nèi)置的四大核心函數(shù)式接口的用法實(shí)例,需要的朋友可以參考下
    2021-06-06
  • spring配置定時(shí)任務(wù)的幾種方式總結(jié)

    spring配置定時(shí)任務(wù)的幾種方式總結(jié)

    這篇文章主要介紹了spring配置定時(shí)任務(wù)的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評(píng)論