日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

线程调度、公平锁和非公平锁、乐观锁和悲观锁、锁优化、重入锁

發(fā)布時(shí)間:2024/10/14 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程调度、公平锁和非公平锁、乐观锁和悲观锁、锁优化、重入锁 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 線程調(diào)度

線程調(diào)度指的就是給線程分配使用處理器的過(guò)程。主要的調(diào)度方式有兩種:協(xié)同式調(diào)度和搶占式調(diào)度。

1.1 協(xié)同式調(diào)度

線程完成自己的任務(wù)之后主動(dòng)通知系統(tǒng)切換到另一個(gè)線程上。

優(yōu)點(diǎn):

實(shí)現(xiàn)簡(jiǎn)單,線程對(duì)于自己的切換是已知的,不存在線程同步的問(wèn)題;

缺點(diǎn):

如果一個(gè)線程一直阻塞占用處理器,則其他線程都會(huì)被阻塞。

1.2 搶占式調(diào)度

由系統(tǒng)來(lái)為線程分配使用處理器的時(shí)間片。

優(yōu)點(diǎn):

線程的執(zhí)行時(shí)間是系統(tǒng)可控的,不會(huì)出現(xiàn)一個(gè)線程導(dǎo)致整個(gè)進(jìn)程阻塞的問(wèn)題。

Java使用的線程調(diào)度就是搶占式調(diào)度。

2. 公平鎖與非公平鎖

公平鎖是多個(gè)線程在等待同一個(gè)鎖時(shí),必須按照申請(qǐng)鎖的時(shí)間順序來(lái)一次獲得鎖(默認(rèn)的是不公平鎖);

非公平鎖就是一種獲取鎖的搶占機(jī)制,是隨機(jī)獲得鎖的,和公平鎖不一樣的就是先來(lái)的不一定先得到鎖。

3. 樂(lè)觀鎖和悲觀鎖

3.1 悲觀鎖

悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀。

每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。

傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

3.2 樂(lè)觀鎖

樂(lè)觀鎖(Optimistic Lock), 顧名思義,就是很樂(lè)觀。

每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制。

樂(lè)觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量,像數(shù)據(jù)庫(kù)如果提供類似于write_condition機(jī)制的其實(shí)都是提供的樂(lè)觀鎖。

樂(lè)觀鎖是基于沖突檢測(cè)的樂(lè)觀并發(fā)策略

3.3 應(yīng)用

Synchronized原始采用的就是CPU悲觀鎖機(jī)制,即線程獲取的是獨(dú)占鎖。

  • 獨(dú)占鎖意味著其他線程只能依靠阻塞來(lái)等待線程釋放鎖。

Lock采用的就是樂(lè)觀鎖方式。所謂樂(lè)觀鎖就是,每次不加鎖而是假設(shè)沒(méi)有沖突而去完成某項(xiàng)操作,如果因?yàn)闆_突失敗就重試,直到成功為止。樂(lè)觀鎖實(shí)現(xiàn)的機(jī)制就是CAS操作

4. 鎖優(yōu)化

Java虛擬機(jī)團(tuán)隊(duì)在JDK1.5到JDK1.6之間對(duì)高效并發(fā)進(jìn)行了重要改進(jìn),有以下五種技術(shù),都是為了在線程之間更高效地共享數(shù)據(jù),以及解決競(jìng)爭(zhēng)問(wèn)題,從而提高程序的執(zhí)行效率。

這里的鎖優(yōu)化主要是指 JVM 對(duì) synchronized 的優(yōu)化。

?4.1 自旋鎖和自適應(yīng)鎖

互斥同步進(jìn)入阻塞狀態(tài)的開(kāi)銷都很大,應(yīng)該盡量避免。

在許多應(yīng)用中,共享數(shù)據(jù)的鎖定狀態(tài)只會(huì)持續(xù)很短的一段時(shí)間

自旋鎖的思想是讓一個(gè)線程在請(qǐng)求一個(gè)共享數(shù)據(jù)的鎖時(shí)執(zhí)行忙循環(huán)(自旋) 一段時(shí)間,如果在這段時(shí)間內(nèi)能獲得鎖,就可以避免進(jìn)入阻塞狀態(tài)。

自旋鎖雖然能避免進(jìn)入阻塞狀態(tài)從而減少開(kāi)銷,但是它需要進(jìn)行忙循環(huán)操作占用CPU 時(shí)間,它只適用于共享數(shù)據(jù)的鎖定狀態(tài)很短的場(chǎng)景。

在 JDK 1.6 中引入了自適應(yīng)的自旋鎖。自適應(yīng)意味著自旋的次數(shù)不再固定了,而是由前一次在同一個(gè)鎖上的自旋次數(shù)及鎖的擁有者的狀態(tài)來(lái)決定。

自旋是有限定的次數(shù)的,在JDK 1.6引入了自適應(yīng)自旋

自適應(yīng)意味著自旋的時(shí)間不再固定了,而是由前一次在同一個(gè)鎖上的自旋時(shí)間以及鎖的擁有者的狀態(tài)來(lái)決定。

4.2 鎖消除

鎖消除是指對(duì)于被檢測(cè)出不可能存在競(jìng)爭(zhēng)的共享數(shù)據(jù)的鎖進(jìn)行消除。

鎖消除主要是通過(guò)逃逸分析來(lái)支持,如果堆上的共享數(shù)據(jù)不可能逃逸出去被其它線程訪問(wèn)到,那么就可以把它們當(dāng)成私有數(shù)據(jù)對(duì)待,也就可以將它們的鎖進(jìn)行消除。

對(duì)于一些看起來(lái)沒(méi)有加鎖的代碼,其實(shí)隱式的加了很多鎖。例如下面的字符串拼接代碼就隱式加了鎖:

public static String concatString(String s1, String s2, String s3) {return s1 + s2 + s3; }

String 是一個(gè)不可變的類,編譯器會(huì)對(duì) String 的拼接自動(dòng)優(yōu)化。在 JDK 1.5 之前,會(huì)轉(zhuǎn)化為 StringBuffer 對(duì)象的連續(xù) append() 操作:

public static String concatString(String s1, String s2, String s3) {StringBuffer sb = new StringBuffer();sb.append(s1);sb.append(s2);sb.append(s3);return sb.toString(); }

每個(gè) append() 方法中都有一個(gè)同步塊。

虛擬機(jī)觀察變量 sb,很快就會(huì)發(fā)現(xiàn)它的動(dòng)態(tài)作用域被限制在 concatString() 方法內(nèi)部。

也就是說(shuō),sb 的所有引用永遠(yuǎn)不會(huì)逃逸到 concatString() 方法之外,其他線程無(wú)法訪問(wèn)到它,因此可以進(jìn)行消除。

4.3 鎖粗化

如果一系列的連續(xù)操作都對(duì)同一個(gè)對(duì)象反復(fù)加鎖和解鎖,頻繁的加鎖操作就會(huì)導(dǎo)致性能損耗。

上一節(jié)的示例代碼中連續(xù)的 append() 方法就屬于這類情況。

如果虛擬機(jī)探測(cè)到由這樣的一串零碎的操作都對(duì)同一個(gè)對(duì)象加鎖,將會(huì)把加鎖的范圍擴(kuò)展(粗化) 到整個(gè)操作序列的外部

對(duì)于上一節(jié)的示例代碼就是擴(kuò)展到第一個(gè) append() 操作之前直至最后一個(gè) append() 操作之后,這樣只需要加鎖一次就可以了。


JDK 1.6 引入了偏向鎖和輕量級(jí)鎖,從而讓鎖擁有了四個(gè)狀態(tài):

  • 無(wú)鎖狀態(tài)(unlocked)
  • 偏向鎖狀態(tài)(biasble)
  • 輕量級(jí)鎖狀態(tài)(lightweight locked)
  • 重量級(jí)鎖狀態(tài)(inflated)

4.4 輕量級(jí)鎖

并不是用來(lái)代替重量級(jí)鎖的,它的本意是在沒(méi)有多線程競(jìng)爭(zhēng)的前提下減少傳統(tǒng)重量級(jí)鎖使用操作系統(tǒng)互斥量產(chǎn)生的性能消耗

輕量級(jí)鎖能提升程序同步性能的依據(jù)是“對(duì)于絕大部分的鎖,在整個(gè)同步周期內(nèi)都是不存在競(jìng)爭(zhēng)的”

在無(wú)競(jìng)爭(zhēng)的情況下使用CAS操作避免了使用互斥量的開(kāi)銷,但是如果存在鎖競(jìng)爭(zhēng),除了互斥量的開(kāi)銷外,還額外發(fā)生了CAS操作,因此在有競(jìng)爭(zhēng)的情況下,輕量級(jí)鎖會(huì)比傳統(tǒng)的重量級(jí)鎖更慢。

適用場(chǎng)景:

追求響應(yīng)時(shí)間,同步塊執(zhí)行速度非常快。

使用操作系統(tǒng)互斥量來(lái)實(shí)現(xiàn)的傳統(tǒng)鎖稱為是“重量級(jí)”鎖。

4.5 偏向鎖

目的是消除數(shù)據(jù)在無(wú)競(jìng)爭(zhēng)情況下的同步原語(yǔ),進(jìn)一步提高程序的運(yùn)行性能。偏向鎖會(huì)偏向于第一個(gè)獲得它的線程,如果在后面的執(zhí)行過(guò)程中,該鎖沒(méi)有被其他的線程獲取,則持有偏向鎖的線程將永遠(yuǎn)不需要再進(jìn)行同步。

偏向鎖可以提高帶有同步但無(wú)競(jìng)爭(zhēng)的程序性能。但是如果程序中大多數(shù)的鎖總是被多個(gè)不同的線程訪問(wèn),那偏向模式就是多余的。

適用場(chǎng)景:

只有一個(gè)線程訪問(wèn)同步塊場(chǎng)景。

5. ReentrantLock(可重入鎖)

可重入鎖的三個(gè)特性

5.1 等待可中斷

當(dāng)持有鎖的線程長(zhǎng)期不釋放鎖的時(shí)候,正在等待的線程可以選擇放棄等待,改為處理其他事情。

可中斷特性對(duì)處理執(zhí)行時(shí)間長(zhǎng)的同步塊很有幫助。

5.2 公平鎖與非公平鎖

ReentrantLock默認(rèn)是非公平鎖,但是可以通過(guò)帶布爾值的構(gòu)造函數(shù)要求使用公平鎖。

公平鎖是多個(gè)線程在等待同一個(gè)鎖時(shí),必須按照申請(qǐng)鎖的時(shí)間順序來(lái)一次獲得鎖(默認(rèn)的是不公平鎖);

非公平鎖就是一種獲取鎖的搶占機(jī)制,是隨機(jī)獲得鎖的,和公平鎖不一樣的就是先來(lái)的不一定先得到鎖。

5.3

鎖可以綁定多個(gè)條件condition,可以選擇性通知指定的某個(gè)種類的condition。

6.怎么檢查一個(gè)線程是否擁有鎖?

在java.lang.Thread中有一個(gè)方法叫holdsLock(),它返回true如果當(dāng)且僅當(dāng)當(dāng)前線程擁有某個(gè)具體對(duì)象的鎖。

7. Lock與synchronized的區(qū)別

7.1 是否為語(yǔ)言內(nèi)置:

synchronized是Java語(yǔ)言的關(guān)鍵字,因此是內(nèi)置特性

Lock不是Java語(yǔ)言內(nèi)置的,是一個(gè)類,通過(guò)這個(gè)類可以實(shí)現(xiàn)同步訪問(wèn)

7.2 用法

synchronzied可以用于去修飾方法或代碼塊,而Lock則需要在代碼中顯示的通過(guò)調(diào)用lock()和unlock()方法來(lái)指定起始位置和終止位置。synchronize是托管給JVM的,而Lock的鎖定是通過(guò)代碼實(shí)現(xiàn)的,它有比synchronized更精確的線程語(yǔ)義。

7.3 鎖機(jī)制

Lock和synchronized有一點(diǎn)非常大的不同,

采用synchronized不需要用戶去手動(dòng)釋放鎖,當(dāng)synchronized方法或者synchronized代碼塊執(zhí)行完之后,系統(tǒng)會(huì)自動(dòng)讓線程釋放對(duì)鎖的占用;

而Lock則必須要用戶去手動(dòng)釋放鎖,如果沒(méi)有主動(dòng)釋放鎖,就有可能導(dǎo)致出現(xiàn)死鎖現(xiàn)象;

7.4 并發(fā)量對(duì)性能的影響

并發(fā)數(shù)量多的時(shí)候synchronized性能會(huì)下降很厲害,但是對(duì)Lock影響不大。

7.5 Lock可以提高多個(gè)線程進(jìn)行讀操作的效率。

?

總結(jié)

以上是生活随笔為你收集整理的线程调度、公平锁和非公平锁、乐观锁和悲观锁、锁优化、重入锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。