日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

更多內(nèi)容,歡迎關(guān)注微信公眾號(hào):全菜工程師小輝~

Lock接口的實(shí)現(xiàn)類

ReentrantLock是實(shí)現(xiàn)了Lock接口的類,屬于獨(dú)享鎖,獨(dú)享鎖在同一時(shí)刻僅有一個(gè)線程可以進(jìn)行訪問(wèn)。Lock接口很簡(jiǎn)單,實(shí)現(xiàn)了如下:

public interface Lock {
 void lock();
 void lockInterruptibly() throws InterruptedException;
 boolean tryLock();
 boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
 void unlock();
 Condition newCondition();
}

lock()和unlock()

lock()和unlock()必須成對(duì)出現(xiàn)。一般來(lái)說(shuō),使用lock必須在try{}塊中進(jìn)行,并且將釋放鎖的操作放在finally塊中進(jìn)行,以保證鎖一定被被釋放,防止死鎖的發(fā)生。通常使用ReentrantLock來(lái)進(jìn)行同步的話,是以下面這種形式去使用的:

ReentrantLock lock = ...;
lock.lock();
try{
 //處理任務(wù)
}catch(Exception ex){
 
}finally{
 lock.unlock(); //釋放鎖
}

tryLock()

tryLock()方法是有返回值的,它表示用來(lái)嘗試獲取鎖,如果獲取成功,則返回true,如果獲取失敗(即鎖已被其他線程獲取),則返回false,也就說(shuō)這個(gè)方法無(wú)論如何都會(huì)立即返回。在拿不到鎖時(shí)不會(huì)一直在那等待。

tryLock(long time, TimeUnit unit)

tryLock(long time, TimeUnit unit)方法和tryLock()方法是類似的,只不過(guò)區(qū)別在于這個(gè)方法在拿不到鎖時(shí)會(huì)等待一定的時(shí)間,在時(shí)間期限之內(nèi)如果還拿不到鎖,就返回false。如果如果一開(kāi)始拿到鎖或者在等待期間內(nèi)拿到了鎖,則返回true。

lockInterruptibly()

這是一個(gè)可中斷的獲取鎖方法。

如果沒(méi)有其他線程持有鎖,則當(dāng)前線程獲取到鎖,并為鎖計(jì)數(shù)加1,并且立即返回;如果當(dāng)前線程已經(jīng)持有鎖,則為鎖計(jì)數(shù)加1,并立即返回。

如果其他線程持有鎖,則當(dāng)前線程將休眠直到下面兩個(gè)事件中的一個(gè)發(fā)生:

  1. 當(dāng)前線程獲取到鎖
  2. 其他線程中斷當(dāng)前線程

簡(jiǎn)而言之,lockInterruptibly()在線程等待鎖期間是可以被interrupt的,而lock()在多線程等待鎖期間是無(wú)視interrupt的。

實(shí)驗(yàn)示例:

class MyThread {
 public static void main(String[] args) throws InterruptedException {
 final Lock lock = new ReentrantLock();
 lock.lock();
 Thread t1 = new Thread(() -> {
 lock.lock(); //注釋這行把下面注釋打開(kāi)再試試
// try {
// lock.lockInterruptibly();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
 System.out.println(Thread.currentThread().getName() + " interrupted.");
 });
 t1.start();
 Thread.sleep(1000);
 t1.interrupt();
 Thread.sleep(3000);
 }
}

注意,當(dāng)一個(gè)線程獲取了鎖之后,是不會(huì)被interrupt()方法中斷的。因?yàn)閱为?dú)調(diào)用interrupt()方法不能中斷正在運(yùn)行過(guò)程中的線程,只能中斷阻塞過(guò)程中的線程。

ReadWriteLock接口的實(shí)現(xiàn)類

ReadWriteLock也是一個(gè)接口,在它里面只定義了兩個(gè)方法:

public interface ReadWriteLock {
 /**
 * Returns the lock used for reading.
 *
 * @return the lock used for reading.
 */
 Lock readLock();
 
 /**
 * Returns the lock used for writing.
 *
 * @return the lock used for writing.
 */
 Lock writeLock();
}

一個(gè)用來(lái)獲取讀鎖,一個(gè)用來(lái)獲取寫(xiě)鎖。也就是說(shuō)將文件的讀寫(xiě)操作分開(kāi),分成2個(gè)鎖來(lái)分配給線程,從而使得多個(gè)線程可以同時(shí)進(jìn)行讀操作。ReentrantReadWriteLock實(shí)現(xiàn)了ReadWriteLock接口。

線程進(jìn)入讀鎖的前提條件:

  1. 沒(méi)有其他線程的寫(xiě)鎖,
  2. 沒(méi)有寫(xiě)請(qǐng)求或者有寫(xiě)請(qǐng)求,但調(diào)用線程和持有鎖的線程是同一個(gè)
  3. 線程進(jìn)入寫(xiě)鎖的前提條件:
  4. 沒(méi)有其他線程的讀鎖
  5. 沒(méi)有其他線程的寫(xiě)鎖

ReentrantReadWriteLock支持以下功能:

  1. 支持公平和非公平的獲取鎖的方式;
  2. 支持可重入。讀線程在獲取了讀鎖后還可以獲取讀鎖;寫(xiě)線程在獲取了寫(xiě)鎖之后既可以再次獲取寫(xiě)鎖又可以獲取讀鎖;
  3. 還允許從寫(xiě)入鎖降級(jí)為讀取鎖,其實(shí)現(xiàn)方式是:先獲取寫(xiě)入鎖,然后獲取讀取鎖,最后釋放寫(xiě)入鎖。但是,從讀取鎖升級(jí)到寫(xiě)入鎖是不允許的;
  4. 讀取鎖和寫(xiě)入鎖都支持鎖獲取期間的中斷;
  5. Condition支持。僅寫(xiě)入鎖提供了一個(gè) Conditon 實(shí)現(xiàn);讀取鎖不支持 Conditon ,readLock().newCondition() 會(huì)拋出 UnsupportedOperationException。

ReentrantReadWriteLock里面提供了很多豐富的方法,不過(guò)最主要的有兩個(gè)方法:readLock()和writeLock()用來(lái)獲取讀鎖和寫(xiě)鎖。

使用實(shí)例:

public class Test {
 private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
 
 public static void main(String[] args) {
 final Test test = new Test();
 
 new Thread(){
 public void run() {
 test.get(Thread.currentThread());
 };
 }.start();
 
 new Thread(){
 public void run() {
 test.get(Thread.currentThread());
 };
 }.start();
 
 } 
 // 如果將函數(shù)改成synchronized的,會(huì)降低多線程的執(zhí)行效率
 public void get(Thread thread) {
 rwl.readLock().lock();
 try {
 long start = System.currentTimeMillis();
 
 while(System.currentTimeMillis() - start <= 1) {
 System.out.println(thread.getName()+"正在進(jìn)行讀操作");
 }
 System.out.println(thread.getName()+"讀操作完畢");
 } finally {
 rwl.readLock().unlock();
 }
 }
}

Lock/ReadWriteLock和synchronized的區(qū)別:

總結(jié)來(lái)說(shuō),Lock和synchronized有以下幾點(diǎn)不同:

  1. Lock是一個(gè)接口,而synchronized是JAVA中的關(guān)鍵字,synchronized是內(nèi)置的語(yǔ)言實(shí)現(xiàn)
  2. synchronized在發(fā)生異常時(shí),會(huì)自動(dòng)釋放線程占有的鎖,因此不會(huì)導(dǎo)致死鎖現(xiàn)象發(fā)生;而Lock在發(fā)生異常時(shí),如果沒(méi)有主動(dòng)通過(guò)unLock()去釋放鎖,則很可能造成死鎖現(xiàn)象,因此使用Lock時(shí)需要在finally塊中釋放鎖
  3. Lock可以讓等待鎖的線程響應(yīng)中斷,而synchronized卻不行,使用synchronized時(shí),等待的線程會(huì)一直等待下去,不能夠響應(yīng)中斷
  4. 通過(guò)Lock可以知道有沒(méi)有成功獲取鎖,而synchronized卻無(wú)法辦到
  5. Lock可以提高多個(gè)線程進(jìn)行讀操作的效率

官方表示,他們更支持synchronize,在未來(lái)的版本中還有優(yōu)化余地,所以還是提倡在synchronized能實(shí)現(xiàn)需求的情況下,優(yōu)先考慮使用synchronized來(lái)進(jìn)行同步。

分享到:
標(biāo)簽:多線程 Java
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定