java之lock的使用(Java中的lock)

本文目錄一覽:

如何使用java的鎖機制

可以在臨界區代碼開始的位置執行Lock類的lock方法,為代碼塊加鎖,而在臨界區的出口使用相同Lock實例的unlock方法,釋放臨界區資源。

Demo2-12中,主線程先創建了一個lockTest對象test,然後將相同的test對象交給兩個不同的線程執行。子線程1獲取到了lock後,開始執行before sleep輸出語句,遇到sleep後,線程1阻塞將會放棄執行權,這時線程2可以獲取執行權,當線程2執行lock方法時,發現鎖已經被別的線程獲取,所以線程2阻塞等待lock的釋放。線程1從sleep中被喚醒後,將繼續執行after sleep語句,之後釋放了鎖,此時線程2從鎖等待中被喚醒,執行臨近區的內容,因此Demo2-12的輸出是先線程1的兩條語句,之後才輸出線程2的兩條語句。而Demo2-13在沒有鎖的保護下,程序無法保證先將線程1的兩條語句輸出後再執行線程2的輸出,因此,Demo2-13的輸出結果是交叉的。

java Lock鎖為什麼不直接使用

主要為了多線程訪問共享資源時,保證只能有一個線程操作資源,比如說一個servlet中對根據參數 一個公共變數設置值 ,如果不採用lock那麼在並發訪問時就無法保證每個線程中公共變數設置的值都是各自線程的,在後續的應用中變數的值可能會錯亂,加了lock之後就保證了在一個線程中從頭到尾都是一致的

Java中lock類該怎麼用啊?可以完全代替synchronize嗎?

1、上鎖(漂亮的寫法是先判斷是否鎖被佔用)

2、你要執行的命令(比如讀取io和資料庫 釋放相關資源)

3、釋放鎖

然後別的地方就是重複以上三步的過程

synchronize就是把1和3替換成了{ }

完全替代到不一定 畢竟synchronize使用起來簡單明了

關於java的lock和condition

1、在某些情況下,當內部鎖非常不靈活時,顯式鎖就可以派上用場。內部條件隊列有一些缺陷,每個內部鎖只能有一個與之相關聯的條件隊列。

2、使用顯式的Lock和Condition的實現類提供了一個比內部鎖和條件隊列更加靈活的選擇。一個Condition和一個單獨的Lock相關聯,就像條件隊列和單獨的內部鎖相關聯一樣。每個鎖可以有多個等待集、中斷性選擇、基於時限、公平性選擇等。

public interface Condition{

void await() throws InterruptedException;//相當於wait

boolean await(long time,TimeUnit unit) throws InterruptedException;

long awaitNanos(long nanosTimeout) throws InterruptedException;

void awaitUninterruptibly();

boolean awaitUntil(Date deadline) throws InterruptedException;

void signal();//相當於notify

void signalAll();//相當於notifyall

}

調用與Condition相關聯的Lock的Lock.newCondition方法,可創建一個Condition.

3、有限緩存操作

@ThreadSafe

public class ConditionBoundedBufferT{

protected final Lock lock=new ReentrantLock();

private final Condition notFull=lock.newCondition();

private final Condition notEmpty=lock.newCondition();

@GuardBy(“lock”);

private final T[] items=(T[]) new Object[BUFFER_SIZE];

@GuardBy(“lock”) private int tail,head,count;

public void put(T x) throws InterruptedExceptoin{

lock.lock();

try{

while (count=items.lentgh)

notFull.await();

items[tail]=x;

if (++tail=items.length)

tail=0;

++count;

notEmpty.signal();

}

finally{lock.unlock();

}

}

public T take() throws InterruptedException{

lock.lock();

try{

while (count=items.lentgh)

notEmpty.await();

T x=items[head];

items[head]=null;

if (++head=items.length)

head=0;

–count;

notFull.signal();

return x;

}

finally{lock.unlock();

}

}

}

Java中Lock,tryLock,lockInterruptibly有什麼區別

Java中Lock,tryLock,lockInterruptibly的區別如下:

一、 lock()方法

使用lock()獲取鎖,若獲取成功,標記下是該線程獲取到了鎖(用於鎖重入),然後返回。若獲取失敗,這時跑一個for循環,循環中先將線程阻塞放入等待隊列,當被調用signal()時線程被喚醒,這時進行鎖競爭(因為默認使用的是非公平鎖),如果此時用CAS獲取到了鎖那麼就返回,如果沒獲取到那麼再次放入等待隊列,等待喚醒,如此循環。其間就算外部調用了interrupt(),循環也會繼續走下去。一直到當前線程獲取到了這個鎖,此時才處理interrupt標誌,若有,則執行 Thread.currentThread().interrupt(),結果如何取決於外層的處理。lock()最終執行的方法如下:

[java] view plain copy

final boolean acquireQueued(final Node node, int arg) {

boolean failed = true;

try {

boolean interrupted = false;

for (;;) {

final Node p = node.predecessor();

if (p == head tryAcquire(arg)) { //如果競爭得到了鎖

setHead(node);

p.next = null; // help GC

failed = false;

return interrupted; //獲取成功返回interrupted標誌

}

// 只修改標誌位,不做其他處理

if (shouldParkAfterFailedAcquire(p, node) strongparkAndCheckInterrupt()/strong)

interrupted = true;

}

} finally {

if (failed)

cancelAcquire(node);

}

}

其中parkAndCheckInterrupt()調用了LockSupport.park(),該方法使用Unsafe類將進程阻塞並放入等待隊列,等待喚醒,和await()有點類似。

可以看到循環中檢測到了interrupt標記,但是僅做 interrupted = true 操作,直到獲取到了鎖,才return interrupted,然後處理如下

[java] view plain copy

public final void acquire(int arg) {

if (!tryAcquire(arg) acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

selfInterrupt(); // 執行Thread.currentThread().interrupt()

}

二、 lockInterruptibly()方法

和lock()相比,lockInterruptibly()只有略微的修改,for循環過程中,如果檢測到interrupt標誌為true,則立刻拋出InterruptedException異常,這時程序變通過異常直接返回到最外層了,又外層繼續處理,因此使用lockInterruptibly()時必須捕捉異常。lockInterruptibly()最終執行的方法如下:

[java] view plain copy

private void doAcquireInterruptibly(int arg)

throws InterruptedException {

final Node node = addWaiter(Node.EXCLUSIVE);

boolean failed = true;

try {

for (;;) {

final Node p = node.predecessor();

if (p == head tryAcquire(arg)) {

setHead(node);

p.next = null; // help GC

failed = false;

return; //獲取成功返回

}

if (shouldParkAfterFailedAcquire(p, node)

parkAndCheckInterrupt())

throw new InterruptedException(); //直接拋出異常

}

} finally {

if (failed)

cancelAcquire(node);

}

}

三、 tryLock()方法

使用tryLock()嘗試獲取鎖,若獲取成功,標記下是該線程獲取到了鎖,然後返回true;若獲取失敗,此時直接返回false,告訴外層沒有獲取到鎖,之後的操作取決於外層,代碼如下:

[java] view plain copy

final boolean nonfairTryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

return true;

}

}

else if (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc 0) // overflow

throw new Error(“Maximum lock count exceeded”);

setState(nextc);

return true;

}

return false;

}

深入研究 Java Synchronize 和 Lock 的區別與用法

一、synchronized和lock的用法區別

synchronized:在需要同步的對象中加入此控制,synchronized可以加在方法上,也可以加在特定代碼塊中,括弧中表示需要鎖的對象。

lock:需要顯示指定起始位置和終止位置。一般使用ReentrantLock類做為鎖,多個線程中必須要使用一個ReentrantLock類做為對象才能保證鎖的生效。且在加鎖和解鎖處需要通過lock()和unlock()顯示指出。所以一般會在finally塊中寫unlock()以防死鎖。

 

 

二、synchronized和lock用途區別

synchronized原語和ReentrantLock在一般情況下沒有什麼區別,但是在非常複雜的同步應用中,請考慮使用ReentrantLock,特別是遇到下面2種需求的時候。

1.某個線程在等待一個鎖的控制權的這段時間需要中斷

2.需要分開處理一些wait-notify,ReentrantLock裡面的Condition應用,能夠控制notify哪個線程

3.具有公平鎖功能,每個到來的線程都將排隊等候

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/236873.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:02
下一篇 2024-12-12 12:02

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論