成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

淺談java中的并發(fā)控制

Gilbertat / 1522人閱讀

摘要:并發(fā)需要解決的問題功能性問題線程同步面臨兩個問題,想象下有兩個線程在協(xié)作工作完成某項任務。鎖可用于規(guī)定一個臨界區(qū),同一時間臨界區(qū)內(nèi)僅能由一個線程訪問。并發(fā)的數(shù)據(jù)結構線程安全的容器,如等。

并發(fā)指在宏觀上的同一時間內(nèi)同時執(zhí)行多個任務。為了滿足這一需求,現(xiàn)代的操作系統(tǒng)都抽象出 線程 的概念,供上層應用使用。

這篇博文不打算詳細展開分析,而是對java并發(fā)中的概念和工具做一個梳理。
沿著并發(fā)模型、并發(fā)要解決的問題、基本工具、衍生工具這一思路展開。

線程

首先線程是什么?線程是由OS抽象并實現(xiàn)的,我們知道OS的職責是管理并合理分配硬件資源,那么OS為了更好的管理、分配CPU資源,同時也為了滿足同時執(zhí)行任務這一需求,設計了線程這一概念。

雖然java程序運行在JVM虛擬機上,但是java的線程仍然是對操作系統(tǒng)原生線程的封裝,同時,jvm對線程實現(xiàn)時也將jvm的運行棧設計成線程私有內(nèi)存,因此,java線程和原生線程在理解上實際上沒太大區(qū)別。

線程的五種狀態(tài):

graph LR
新建 --> 就緒;
就緒 --> 運行;
運行 --> 就緒;
運行 --> 阻塞;
阻塞 --> 就緒;
運行 --> 死亡;

先來看上面的就緒狀態(tài)和運行狀態(tài)。我們知道線程雖然宏觀上是同時執(zhí)行的,但是微觀上使用如時間片輪轉(zhuǎn)算法使得線程依次執(zhí)行。那么,同一時間只有一個線程執(zhí)行,其它需要執(zhí)行的線程處于 就緒隊列 中,等待自己被調(diào)度到。

而如果線程想要暫時放棄在CPU上運行的權利,就會阻塞自己。這時對應著阻塞狀態(tài),同時線程會從就緒隊列中移除,進入等待隊列。
很顯然,阻塞線程被喚醒肯定是進入就緒隊列等待調(diào)度,而不可能是直接分配到CPU上運行。

在線程同步時,線程可能由于以下情況被阻塞:

同步阻塞。就是被鎖阻塞。

等待阻塞。被條件變量阻塞。

其它。調(diào)用sleep(), join()或等待IO操作時的阻塞。

并發(fā)需要解決的問題 功能性問題

線程同步面臨兩個問題,想象下有兩個線程在協(xié)作工作完成某項任務。那么需要解決以下問題:

線程兩個線程之間交互數(shù)據(jù),必然涉及到數(shù)據(jù)共享。而某些數(shù)據(jù)資源無法被多個線程同時使用(臨界區(qū)),這時需要,即線程互斥問題。

假如一個線程進行的太快,另外一個線程就需要等等它,即線程同步問題。

性能和可用性問題

在多線程程序的性能問題上,如果是對于同樣一段臨界區(qū)的多線程訪問,那么則有以下幾個思路:

互斥鎖?;コ怄i即保證同一時間只有一個線程訪問臨界區(qū)并完整執(zhí)行完,其它線程在臨界區(qū)外面等待。

無障礙或無鎖。線程們一開始直接進入臨界區(qū)執(zhí)行,注意其中不能修改共享數(shù)據(jù)。執(zhí)行完后再判斷剛才這段時間是否有其它線程執(zhí)行,沒有的話才修改共享數(shù)據(jù),如果有的話就回滾重來。

降低鎖粒度。也即將這個大的臨界區(qū)拆分成幾個小的臨界區(qū),分別加互斥鎖控制,這樣提高了線程同時訪問的臨界區(qū)的機會變多,性能提高。顯然這要對代碼仔細推敲,考慮如何拆分鎖粒度而不影響整體的語義。

以上三種思路的性能優(yōu)劣沒有一個普適的結果,和具體的場景相關。

并發(fā)中還會出現(xiàn)以下幾種情況導致系統(tǒng)不可用:

死鎖。不解釋。

饑餓。線程調(diào)度算法如果不是平等分配的,那么就可能出現(xiàn)優(yōu)先級高的線程長時間占用CPU,導致優(yōu)先級低的線程無法得到執(zhí)行機會。

活鎖。這個我解釋不來。。。

并發(fā)代碼的幾個性質(zhì)

并發(fā)編程中需要考慮的幾個概念:

原子性:指某個操作一旦被某個線程執(zhí)行,直到該操作執(zhí)行完畢都不會有其它線程來干擾。

可見性:指某個變量或某塊內(nèi)存如果被A線程修改,B線程能否馬上讀取到修改后的值。

有序性:A線程執(zhí)行的代碼序列,在B線程看來是否是有序的。

從我個人的理解來看,原子性屬于由并發(fā)和線程這一理論概念自然而然推導衍生而來的概念,而可見性和有序性是具體的工程實踐中產(chǎn)生的。
實際中,jvm并不能實現(xiàn)的特別完美,總會有工程上的妥協(xié)。理論模型與實際模型無法完美契合,總存在一定的偏差。
比如說,jvm為了向性能妥協(xié)使用了緩存機制,犧牲了數(shù)據(jù)一致性,這就產(chǎn)生了可見性的概念,需要程序員編程時自己控制。
jvm為了指令更高效率的執(zhí)行進行了指令重排優(yōu)化,則產(chǎn)生了有序性的問題。印象里以前大學里學過的CPU的流水線技術,為了指令能夠更好的被CPU流水線利用,減少流水線的空閑時間,編譯器編譯時也會在不影響 串行語義 的前提下,進行指令重排。
總而言之,這是在性能和理論模型完整性之間的一種妥協(xié)。

并發(fā)的工具

技術上的工具、概念繁多復雜,但是如果我們能理解技術設計上無時無刻的不運用抽象和分層的手段,
那么,我們可以把技術上的工具分為兩種:

最基本的、原生的工具。

在原生提供的工具上,進行封裝得到的更高層次的工具。

更高層次的工具對基礎工具進行了抽象和封裝,屏蔽了其中的實現(xiàn)細節(jié)。
這里想強調(diào)的是,工具的接口實現(xiàn)是分開的,兩者可以沒有關系。
如java的監(jiān)視器鎖從接口上來看,其語義和互斥鎖一樣。然而它并不一定使用互斥鎖實現(xiàn),而是可以為了性能存在優(yōu)化,只要最終的行為與接口相同即可。

基本工具 鎖、條件變量、信號量

有三種用于線程同步的工具:

鎖。鎖可用于規(guī)定一個 臨界區(qū),同一時間臨界區(qū)內(nèi)僅能由一個線程訪問。其他線程則在臨界區(qū)外等待(阻塞)。

互斥鎖。使用信號量實現(xiàn)。臨界區(qū)外等待的線程會被阻塞。

自旋鎖。臨界區(qū)外等待的線程會忙等。

條件變量(Condition)。線程在某種條件不滿足時阻塞自己,等待其它的線程條件滿足時再喚醒它們。很顯然所有等待的線程要放入一個數(shù)據(jù)結構中,這個數(shù)據(jù)結構就在條件變量內(nèi)。

信號量。操作系統(tǒng)原生的機制。實際上,鎖 + 條件變量可完成所有信號量可以完成的邏輯。

在java中,Object類有wait()、notify()和notifyAll()之類的方法。
這些方法可以認為每個對象都內(nèi)置了一個條件變量,而這些方法是對這些條件變量的操作,因此,可以使用這些方法將對象當作條件變量使用,從而做到線程的同步。

無狀態(tài)編程 底層機制直接對應得到的

底層機制的特點直接得到的:

1. java中的volatile關鍵字。
2. CAS。

volatile關鍵字能夠保證變量的可見性,或者說是讀或?qū)懙脑有浴?/p>

CAS即compareAndSwap,原子操作 。
CAS操作直接能夠?qū)絾螚lCPU指令,因此天然具有原子性。java中是通過JNI調(diào)用C語言從而調(diào)用CPU底層指令實現(xiàn)。

CAS的行為和以下代碼一致:

int cas(long *addr, long old, long new)
{
    if (*addr == old) {
        *addr = new;
        return 1;
    } else {
        return 0; //*
    }
}

那么CAS可以做什么呢?很多樂觀并發(fā)控制可以基于CAS實現(xiàn)。
比如說,通過一個標記變量來記錄臨界區(qū)被誰占有,線程進入臨界區(qū)前不斷的使用CAS操作判斷標記變量是否為空同時將其記錄為自己,來實現(xiàn)鎖機制。這就是自旋鎖的思路。

除此之外,樂觀鎖也能用CAS實現(xiàn),比如java的Atomic系列,就是這樣實現(xiàn)的。

由基本工具封裝、優(yōu)化而成的衍生工具 synchronized關鍵字

前面說到可以認為每個對象內(nèi)置一個條件變量,同樣,每個對象也內(nèi)置一個鎖。這個內(nèi)置鎖在Java中被抽象為監(jiān)視器鎖(monitor)。
synchronized關鍵字的使用實際上就相當于使用監(jiān)視器鎖定義了一個臨界區(qū)。使用這種語法也特別直觀簡單,所以java經(jīng)常用synchronizd來進行線程的同步。

JDK1.6之后,為了提升監(jiān)視器鎖的性能,java通過某些手段進行了優(yōu)化。其中包含鎖優(yōu)化機制,對應三種鎖:

1. 偏向鎖
2. 輕量級鎖
3. 重量級鎖

一開始只有一個線程使用線程時使用偏向鎖,當存在多個線程使用時膨脹為輕量級鎖,而出現(xiàn)比較多的線程競爭時再膨脹為重量級鎖。

并發(fā)的數(shù)據(jù)結構

線程安全的容器,如Vector 、 ConcurrentHashMap等。

讀寫鎖,即java中的ReentrantReadWriteLock。
讀寫鎖又可以看做一個讀鎖和一個寫鎖組成的鎖系統(tǒng),讀鎖和寫鎖又叫共享鎖和排它鎖。

BlockedQueue,阻塞隊列。

Atomic。 java提供的atomic包封裝了一組常用原子類,使用無鎖方式實現(xiàn)。

ThreadLocal。每個線程都擁有一份對象拷貝,互相不干擾。

其它:

雙重檢查鎖

實際上是一種對于線程安全的懶漢單例模式的一種優(yōu)化。

鎖的屬性

為了表達某種鎖的特點,也會有著很多的概念。
但是這種概念對應的不是某一種鎖,而是一類擁有特定屬性的鎖。如:

悲觀鎖和樂觀鎖。
悲觀鎖假設發(fā)生沖突,并使用各種方式保證一次只有一個線程使用臨界區(qū)。
樂觀鎖放任線程去使用資源,在執(zhí)行完后判斷剛才是否有其它線程用過(破壞了數(shù)據(jù)完整性),如果是則撤回重試。

公平鎖和非公平鎖。
公平鎖是指多個線程在等待同一個鎖時,必須按照申請鎖的先后順序來一次獲得鎖。java中的ReentrantLock是公平鎖。

遞歸鎖(可重入鎖)/非遞歸鎖(不可重入鎖)
同一個線程可以多次獲取同一個遞歸鎖,不會產(chǎn)生死鎖。
如果一個線程多次獲取同一個非遞歸鎖,則會產(chǎn)生死鎖。

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/71470.html

相關文章

  • 淺談Java并發(fā)編程系列(八)—— LockSupport原理剖析

    摘要:此對象在線程受阻塞時被記錄,以允許監(jiān)視工具和診斷工具確定線程受阻塞的原因。阻塞當前線程,最長不超過納秒,返回條件在的基礎上增加了超時返回。喚醒線程喚醒處于阻塞狀態(tài)的線程。 LockSupport 用法簡介 LockSupport 和 CAS 是Java并發(fā)包中很多并發(fā)工具控制機制的基礎,它們底層其實都是依賴Unsafe實現(xiàn)。 LockSupport是用來創(chuàng)建鎖和其他同步類的基本線程阻塞...

    jeyhan 評論0 收藏0
  • Java并發(fā)核心淺談

    摘要:耐心看完的你或多或少會有收獲并發(fā)的核心就是包,而的核心是抽象隊列同步器,簡稱,一些鎖啊信號量啊循環(huán)屏障啊都是基于。 耐心看完的你或多或少會有收獲! Java并發(fā)的核心就是 java.util.concurrent 包,而 j.u.c 的核心是AbstractQueuedSynchronizer抽象隊列同步器,簡稱 AQS,一些鎖??!信號量??!循環(huán)屏障??!都是基于AQS。而 AQS 又是...

    cppowboy 評論0 收藏0
  • 淺談Java并發(fā)編程系列(五)—— ReentrantLock VS synchronized

    摘要:線程通過的方法獲得鎖,用方法釋放鎖。和關鍵字的區(qū)別在等待鎖時可以使用方法選擇中斷,改為處理其他事情,而關鍵字,線程需要一直等待下去。擁有方便的方法用于獲取正在等待鎖的線程。 ReentrantLock是Java并發(fā)包中一個非常有用的組件,一些并發(fā)集合類也是用ReentrantLock實現(xiàn),包括ConcurrentHashMap。ReentrantLock具有三個特性:等待可中斷、可實現(xiàn)...

    Ocean 評論0 收藏0
  • 淺談Java并發(fā)編程系列(二)—— Java內(nèi)存模型

    摘要:物理計算機并發(fā)問題在介紹內(nèi)存模型之前,先簡單了解下物理計算機中的并發(fā)問題?;诟咚倬彺娴拇鎯换ヒ胍粋€新的問題緩存一致性。寫入作用于主內(nèi)存變量,把操作從工作內(nèi)存中得到的變量值放入主內(nèi)存的變量中。 物理計算機并發(fā)問題 在介紹Java內(nèi)存模型之前,先簡單了解下物理計算機中的并發(fā)問題。由于處理器的與存儲設置的運算速度有幾個數(shù)量級的差距,所以現(xiàn)代計算機加入一層讀寫速度盡可能接近處理器的高速緩...

    Edison 評論0 收藏0
  • Java學習路線總結,搬磚工逆襲Java架構師(全網(wǎng)最強)

    摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號作者架構師奮斗者掃描主頁左側二維碼,加入群聊,一起學習一起進步歡迎點贊收藏留言前情提要無意間聽到領導們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨立帶隊的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...

    Scorpion 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<