java執行緒安全Lock
對於執行緒安全我們前面使用了synchronized關鍵字,對於執行緒的協作我們使用Object.wait()和Object.notify()。在JDK1.5中java為我們提供了Lock來實現與它們相同的功能,並且效能優於它們,在JDK1.6時,JDK對synchronized做了優化,在效能上兩種方式差距不大了。
一、為什麼出現lock
synchronized修飾的程式碼塊,當一個執行緒獲取了對應的鎖,並執行該程式碼塊時,其他執行緒便只能一直等待,等待獲取鎖的執行緒釋放鎖,如果沒有釋放則需要無限的等待下去。獲取鎖的執行緒釋放鎖只會有兩種情況:
1、獲取鎖的執行緒執行完了該程式碼塊,然後執行緒釋放對鎖的佔有。
2、執行緒執行發生異常,此時JVM會讓執行緒自動釋放鎖。
Lock與synchronized對比:
1、Lock不是Java語言內建的,synchronized是Java語言的關鍵字,因此是內建特性。Lock是一個類,通過這個類可以實現同步訪問。
2、synchronized不需要手動釋放鎖,當synchronized方法或者synchronized程式碼塊執行完之後,系統會自動讓執行緒釋放對鎖的佔用;而Lock則必須要使用者去手動釋放鎖,如果沒有主動釋放鎖,就有可能導致出現死鎖現象。
二、java.util.concurrent.locks包中常用的類和介面。
public interface Lock { //用來獲取鎖。如果鎖已被其他執行緒獲取,則進行等待。 void lock(); // 當通過這個方法去獲取鎖時,如果執行緒正在等待獲取鎖,則這個執行緒能夠響應中斷,即中斷執行緒的等待狀態 void lockInterruptibly() throws InterruptedException; //它表示用來嘗試獲取鎖,如果獲取成功,則返回true,如果獲取失敗(即鎖已被其他執行緒獲取),則返回false boolean tryLock(); //與tryLock()方法是類似的,只不過區別在於這個方法在拿不到鎖時會等待一定的時間,在時間期限之內如果還拿不到鎖,就返回false。如果如果一開始拿到鎖或者在等待期間內拿到了鎖,則返回true。 boolean tryLock(long time, TimeUnit unit) throws InterruptedException; //釋放鎖 void unlock(); Condition newCondition(); }
1、Lock與unlock
Lock用於獲取鎖,但它不會主動釋放鎖所以需要與unlock()配合使用。一般在使用Lock時必須在try{}catch{}塊中進行,並且將釋放鎖的操作放在finally塊中進行,以保證鎖一定被被釋放,防止死鎖的發生。
package com.jalja.base.threadTest;import java.util.concurrent.locks.ReentrantLock;public class LockTest implements Runnable{ public static ReentrantLock lock=new ReentrantLock(); public static int c=0; public void run() { for(int i=0;i<1000;i++){ lock.lock();//獲取鎖 try { System.out.println(Thread.currentThread().getName()+"獲得鎖"); System.out.println(Thread.currentThread().getName()+"====>"+c); c++; } catch (Exception e) { e.printStackTrace(); }finally{ System.out.println(Thread.currentThread().getName()+"釋放鎖"); lock.unlock();//釋放鎖 } } } public static void main(String[] args) { LockTest lt=new LockTest(); Thread thread1=new Thread(lt); Thread thread2=new Thread(lt); thread1.start(); thread2.start(); try { thread1.join(); thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(c); } }
注意:同一個執行緒可以連續獲得同一把鎖,但也必須釋放相同次數的鎖。允許下面的寫法
lock.lock();//獲取鎖 lock.lock(); lock.lock(); try { System.out.println(Thread.currentThread().getName()+"獲得鎖"); System.out.println(Thread.currentThread().getName()+"====>"+c); c++; } catch (Exception e) { e.printStackTrace(); }finally{ System.out.println(Thread.currentThread().getName()+"釋放鎖"); lock.unlock();//釋放鎖 lock.unlock();//釋放鎖 lock.unlock();//釋放鎖 }
2、獲取鎖等待時間tryLock(long time, TimeUnit unit)
如果你約朋友打籃球,約定時間到了你朋友還沒有出現,你等1小時後還是沒到,我想你肯定會掃興的離去。對於執行緒來說也應該時這樣的,因為通常我們是無法判斷一個執行緒為什麼會無法獲得鎖,但我們可以給該執行緒一個獲取鎖的時間限制,如果到時間還沒有獲取到鎖,則放棄獲取鎖。
package com.jalja.base.threadTest;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReentrantLock;public class TryLockTest implements Runnable{ public static ReentrantLock lock=new ReentrantLock(); private static int m=0; public void run() { try { if(lock.tryLock(1, TimeUnit.SECONDS)){//設定獲取鎖的等待時長1秒 System.out.println(Thread.currentThread().getName()+"獲得鎖"); m++; //Thread.sleep(2000);//設定休眠2秒 }else{ System.out.println(Thread.currentThread().getName()+"未獲得鎖"); } } catch (Exception e) { e.printStackTrace(); }finally{ if(lock.isHeldByCurrentThread()){ lock.unlock(); } } } public static void main(String[] args) { TryLockTest thread1=new TryLockTest(); TryLockTest thread2=new TryLockTest(); Thread th1=new Thread(thread1); Thread th2=new Thread(thread2); th1.start(); th2.start(); try { //讓main執行緒等待th1、th2執行緒執行完畢後,再繼續執行 th1.join(); th2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(m); } }
執行結果:
Thread-0獲得鎖 Thread-1獲得鎖2
該程式碼就是讓執行緒在鎖請求中,最多等待1秒,如果超過一秒沒有獲得鎖就返回false,如果獲得了鎖就返回true,根據執行結果可以看出Thread-1執行緒在1秒內獲得了鎖。
我們開啟註釋 //Thread.sleep(2000);就會發現Thread-1或Thread-0一定會有一個是未獲得鎖,這是因為佔用鎖的執行緒時間是2秒,而等待鎖的執行緒等待時間是1秒,所以在1秒後的瞬間它就放棄了請求鎖操作。
相關文章
- Java多執行緒之執行緒同步【synchronized、Lock、volatitle】Java執行緒synchronized
- Java執行緒安全Java執行緒
- Java - 執行緒安全Java執行緒
- Java執行緒(一):執行緒安全與不安全Java執行緒
- 【Java多執行緒】執行緒安全的集合Java執行緒
- Java中的執行緒安全:從synchronized到Lock的深入理解Java執行緒synchronized
- Java多執行緒/併發06、執行緒鎖Lock與ReadWriteLockJava執行緒
- Java 多執行緒基礎(四)執行緒安全Java執行緒
- 詳解Java執行緒安全Java執行緒
- Java 執行緒安全 與 鎖Java執行緒
- Java執行緒安全小結Java執行緒
- java執行緒安全問題Java執行緒
- Java高階-執行緒同步lock與unlock使用Java執行緒
- Java併發實戰一:執行緒與執行緒安全Java執行緒
- Java多執行緒中執行緒安全與鎖問題Java執行緒
- Java基礎之執行緒安全Java執行緒
- java進階(38)--執行緒安全Java執行緒
- 【Java】ConcurrentHashMap執行緒安全技巧JavaHashMap執行緒
- 深入JAVA執行緒安全問題Java執行緒
- java中執行緒安全的集合Java執行緒
- java synchronized 保護執行緒安全Javasynchronized執行緒
- Java多執行緒學習(六)Lock鎖的使用Java執行緒
- java多執行緒:synchronized和lock比較淺析Java執行緒synchronized
- 執行緒3--執行緒安全執行緒
- 執行緒安全和執行緒不安全理解執行緒
- Java多執行緒——執行緒Java執行緒
- 執行緒安全執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- java基礎 關於執行緒安全Java執行緒
- java各種集合的執行緒安全Java執行緒
- java 對執行緒安全支援有哪些?Java執行緒
- JAVA執行緒中的安全知識Java執行緒
- java 雜湊表和執行緒安全Java執行緒
- java web執行緒安全的疑問JavaWeb執行緒
- 多執行緒系列之 執行緒安全執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- iOS多執行緒之執行緒安全iOS執行緒
- Java多執行緒-執行緒中止Java執行緒