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

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

生活随笔

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

编程问答

locks java_java中Locks的使用

發(fā)布時(shí)間:2025/5/22 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 locks java_java中Locks的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

之前文章中我們講到,java中實(shí)現(xiàn)同步的方式是使用synchronized block。在java 5中,Locks被引入了,來(lái)提供更加靈活的同步控制。

本文將會(huì)深入的講解Lock的使用。

Lock和Synchronized Block的區(qū)別

我們?cè)谥暗腟ynchronized Block的文章中講到了使用Synchronized來(lái)實(shí)現(xiàn)java的同步。既然Synchronized Block那么好用,為什么會(huì)引入新的Lock呢?

主要有下面幾點(diǎn)區(qū)別:

synchronized block只能寫(xiě)在一個(gè)方法里面,而Lock的lock()和unlock()可以分別在不同的方法里面。

synchronized block 不支持公平鎖,一旦鎖被釋放,任何線程都有機(jī)會(huì)獲取被釋放的鎖。而使用 Lock APIs則可以支持公平鎖。從而讓等待時(shí)間最長(zhǎng)的線程有限執(zhí)行。

使用synchronized block,如果線程拿不到鎖,將會(huì)被Blocked。 Lock API 提供了一個(gè)tryLock() 的方法,可以判斷是否可以獲得lock,這樣可以減少線程被阻塞的時(shí)間。

當(dāng)線程在等待synchronized block鎖的時(shí)候,是不能被中斷的。如果使用Lock API,則可以使用 lockInterruptibly()來(lái)中斷線程。

Lock interface

我們來(lái)看下Lock interface的定義, Lock interface定義了下面幾個(gè)主要使用的方法:

void lock() - 嘗試獲取鎖,如果獲取不到鎖,則會(huì)進(jìn)入阻塞狀態(tài)。

void lockInterruptibly() - 和lock()很類似,但是它可以將正在阻塞的線程中斷,并拋出java.lang.InterruptedException。

boolean tryLock() – 這是lock()的非阻塞版本,它回嘗試獲取鎖,并立刻返回是否獲取成功。

boolean tryLock(long timeout, TimeUnit timeUnit) – 和tryLock()很像,只是多了一個(gè)嘗試獲取鎖的時(shí)間。

void unlock() – unlock實(shí)例。

Condition newCondition() - 生成一個(gè)和當(dāng)前Lock實(shí)例綁定的Condition。

在使用Lock的時(shí)候,一定要unlocked,以避免死鎖。所以,通常我們我們要在try catch中使用:

Lock lock = ...;

lock.lock();

try {

// access to the shared resource

} finally {

lock.unlock();

}

除了Lock接口,還有一個(gè)ReadWriteLock接口,在其中定義了兩個(gè)方法,實(shí)現(xiàn)了讀鎖和寫(xiě)鎖分離:

Lock readLock() – 返回讀鎖

Lock writeLock() – 返回寫(xiě)鎖

其中讀鎖可以同時(shí)被很多線程獲得,只要不進(jìn)行寫(xiě)操作。寫(xiě)鎖同時(shí)只能被一個(gè)線程獲取。

接下來(lái),我們幾個(gè)Lock的常用是實(shí)現(xiàn)類。

ReentrantLock

ReentrantLock是Lock的一個(gè)實(shí)現(xiàn),什么是ReentrantLock(可重入鎖)呢?

簡(jiǎn)單點(diǎn)說(shuō)可重入鎖就是當(dāng)前線程已經(jīng)獲得了該鎖,如果該線程的其他方法在調(diào)用的時(shí)候也需要獲取該鎖,那么該鎖的lock數(shù)量+1,并且允許進(jìn)入該方法。

不可重入鎖:只判斷這個(gè)鎖有沒(méi)有被鎖上,只要被鎖上申請(qǐng)鎖的線程都會(huì)被要求等待。實(shí)現(xiàn)簡(jiǎn)單

可重入鎖:不僅判斷鎖有沒(méi)有被鎖上,還會(huì)判斷鎖是誰(shuí)鎖上的,當(dāng)就是自己鎖上的時(shí)候,那么他依舊可以再次訪問(wèn)臨界資源,并把加鎖次數(shù)加一。

我們看下怎么使用ReentrantLock:

public void perform() {

lock.lock();

try {

counter++;

} finally {

lock.unlock();

}

}

下面是使用tryLock()的例子:

public void performTryLock() throws InterruptedException {

boolean isLockAcquired = lock.tryLock(1, TimeUnit.SECONDS);

if(isLockAcquired) {

try {

counter++;

} finally {

lock.unlock();

}

}

}

ReentrantReadWriteLock

ReentrantReadWriteLock是ReadWriteLock的一個(gè)實(shí)現(xiàn)。上面也講到了ReadWriteLock主要有兩個(gè)方法:

Read Lock - 如果沒(méi)有線程獲得寫(xiě)鎖,那么可以多個(gè)線程獲得讀鎖。

Write Lock - 如果沒(méi)有其他的線程獲得讀鎖和寫(xiě)鎖,那么只有一個(gè)線程能夠獲得寫(xiě)鎖。

我們看下怎么使用writeLock:

Map syncHashMap = new HashMap<>();

ReadWriteLock lock = new ReentrantReadWriteLock();

Lock writeLock = lock.writeLock();

public void put(String key, String value) {

try {

writeLock.lock();

syncHashMap.put(key, value);

} finally {

writeLock.unlock();

}

}

public String remove(String key){

try {

writeLock.lock();

return syncHashMap.remove(key);

} finally {

writeLock.unlock();

}

}

再看下怎么使用readLock:

Lock readLock = lock.readLock();

public String get(String key){

try {

readLock.lock();

return syncHashMap.get(key);

} finally {

readLock.unlock();

}

}

public boolean containsKey(String key) {

try {

readLock.lock();

return syncHashMap.containsKey(key);

} finally {

readLock.unlock();

}

}

StampedLock

StampedLock也支持讀寫(xiě)鎖,獲取鎖的是會(huì)返回一個(gè)stamp,通過(guò)該stamp來(lái)進(jìn)行釋放鎖操作。

上我們講到了如果寫(xiě)鎖存在的話,讀鎖是無(wú)法被獲取的。但有時(shí)候我們讀操作并不想進(jìn)行加鎖操作,這個(gè)時(shí)候我們就需要使用樂(lè)觀讀鎖。

StampedLock中的stamped類似樂(lè)觀鎖中的版本的概念,當(dāng)我們?cè)?/p>

StampedLock中調(diào)用lock方法的時(shí)候,就會(huì)返回一個(gè)stamp,代表鎖當(dāng)時(shí)的狀態(tài),在樂(lè)觀讀鎖的使用過(guò)程中,在讀取數(shù)據(jù)之后,我們回去判斷該stamp狀態(tài)是否變化,如果變化了就說(shuō)明該stamp被另外的write線程修改了,這說(shuō)明我們之前的讀是無(wú)效的,這個(gè)時(shí)候我們就需要將樂(lè)觀讀鎖升級(jí)為讀鎖,來(lái)重新獲取數(shù)據(jù)。

我們舉個(gè)例子,先看下write排它鎖的情況:

private double x, y;

private final StampedLock sl = new StampedLock();

void move(double deltaX, double deltaY) { // an exclusively locked method

long stamp = sl.writeLock();

try {

x += deltaX;

y += deltaY;

} finally {

sl.unlockWrite(stamp);

}

}

再看下樂(lè)觀讀鎖的情況:

double distanceFromOrigin() { // A read-only method

long stamp = sl.tryOptimisticRead();

double currentX = x, currentY = y;

if (!sl.validate(stamp)) {

stamp = sl.readLock();

try {

currentX = x;

currentY = y;

} finally {

sl.unlockRead(stamp);

}

}

return Math.sqrt(currentX * currentX + currentY * currentY);

}

上面使用tryOptimisticRead()來(lái)嘗試獲取樂(lè)觀讀鎖,然后通過(guò)sl.validate(stamp)來(lái)判斷該stamp是否被改變,如果改變了,說(shuō)明之前的read是無(wú)效的,那么需要重新來(lái)讀取。

最后,StampedLock還提供了一個(gè)將read鎖和樂(lè)觀讀鎖升級(jí)為write鎖的功能:

void moveIfAtOrigin(double newX, double newY) { // upgrade

// Could instead start with optimistic, not read mode

long stamp = sl.readLock();

try {

while (x == 0.0 && y == 0.0) {

long ws = sl.tryConvertToWriteLock(stamp);

if (ws != 0L) {

stamp = ws;

x = newX;

y = newY;

break;

}

else {

sl.unlockRead(stamp);

stamp = sl.writeLock();

}

}

} finally {

sl.unlock(stamp);

}

}

上面的例子是通過(guò)使用tryConvertToWriteLock(stamp)來(lái)實(shí)現(xiàn)升級(jí)的。

Conditions

上面講Lock接口的時(shí)候有提到其中的一個(gè)方法:

Condition newCondition();

Condition提供了await和signal方法,類似于Object中的wait和notify。

不同的是Condition提供了更加細(xì)粒度的等待集劃分。我們舉個(gè)例子:

public class ConditionUsage {

final Lock lock = new ReentrantLock();

final Condition notFull = lock.newCondition();

final Condition notEmpty = lock.newCondition();

final Object[] items = new Object[100];

int putptr, takeptr, count;

public void put(Object x) throws InterruptedException {

lock.lock();

try {

while (count == items.length)

notFull.await();

items[putptr] = x;

if (++putptr == items.length) putptr = 0;

++count;

notEmpty.signal();

} finally {

lock.unlock();

}

}

public Object take() throws InterruptedException {

lock.lock();

try {

while (count == 0)

notEmpty.await();

Object x = items[takeptr];

if (++takeptr == items.length) takeptr = 0;

--count;

notFull.signal();

return x;

} finally {

lock.unlock();

}

}

}

上面的例子實(shí)現(xiàn)了一個(gè)ArrayBlockingQueue,我們可以看到在同一個(gè)Lock實(shí)例中,創(chuàng)建了兩個(gè)Condition,分別代表隊(duì)列未滿,隊(duì)列未空。通過(guò)這種細(xì)粒度的劃分,我們可以更好的控制業(yè)務(wù)邏輯。

總結(jié)

以上是生活随笔為你收集整理的locks java_java中Locks的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

主站蜘蛛池模板: 第一页综合 | 又污又黄的网站 | 深夜成人福利视频 | www.五月天激情 | 亚洲色图一区二区 | 日韩视频免费观看高清完整版 | 中文字幕23 | 精品盗摄一区二区三区 | 中文字幕va| 91丝袜美女 | av尤物在线 | 天天做日日干 | eeuss鲁片一区二区三区在线观看 | 国产一区二区三区黄 | 诱惑av| 一本色道久久综合亚洲精品酒店 | 野战少妇38p | 美女高潮网站 | 爱爱视频欧美 | 99精品国产免费 | 免费中文视频 | 91视频二区| 国产视频福利在线观看 | 欧美激情一区二区 | 亚洲 高清 成人 动漫 | 中文av在线播放 | 欧美另类高清 | 在线免费看av网站 | 男人插入女人阴道视频 | 国产对白自拍 | 加勒比综合网 | 中文字幕第一页在线 | 精品一区二区在线播放 | 自拍偷拍福利视频 | 欧美超碰在线 | 色男人的天堂 | 男人午夜剧场 | 水蜜桃久久| 成人毛毛片| 色哟哟av | 一二区精品 | 国产美女引诱水电工 | 一区二区久久 | jizz91 | 无码国产精品一区二区免费式直播 | 无码人妻精品一区二区三区99v | 亚洲成人自拍 | 国产精品s | 无码精品人妻一区二区三区漫画 | h部分肌肉警猛淫文 | 国产高清一区二区三区四区 | 亚洲热在线 | 看全黄大色黄大片 | 啪啪免费网站 | 三级大片在线观看 | 91porn破解版 | 久章草影院 | 一级全黄色片 | 97狠狠| www.国产精品视频 | 欧美激情性生活 | 亚洲女同志亚洲女同女播放 | 亚洲人成小说 | 久久aⅴ乱码一区二区三区 亚洲成人18 | 性开放淫合集 | 黄色片美女| 国产精品污视频 | 91视频一区二区 | eeuss一区| 亚洲乱色 | 玖草在线观看 | 黄色片在线免费 | 一卡二卡在线视频 | 国产精品美女一区二区三区 | 欧美性极品xxxx做受 | 成人黄色免费在线观看 | 一级片在线免费观看视频 | 黄色资源在线观看 | 先锋影视av | 免费黄色一级 | 欧美激情va永久在线播放 | 免费的污网站 | 国产成人自拍偷拍 | 色综合av综合无码综合网站 | 亚洲精品第一页 | 久久久久久久久久一区 | 成人av一区二区三区在线观看 | 波多野结衣视频免费观看 | 欧美疯狂做受xxxxx高潮 | 久久精品一级片 | 久久久久人妻精品一区二区三区 | 欧美黄色小说视频 | 天天干天天爱天天操 | 欧美h在线观看 | 国产一级在线 | 国产清纯在线 | 国产精品一二三区视频 | 午夜宅男网 | 99re6在线 |