亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁 Java Java基礎(chǔ) Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題

Feb 09, 2021 pm 05:43 PM
java 並發(fā)程式設(shè)計(jì)

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題

免費(fèi)學(xué)習(xí)推薦:java基礎(chǔ)教學(xué)

  • #Lock鎖定與生產(chǎn)者消費(fèi)者問題
  • 傳統(tǒng)Synchronized鎖定
  • Lock鎖定
Synchronized與lock鎖定的差異

傳統(tǒng)的生產(chǎn)者和消費(fèi)者問題

Lock版的生產(chǎn)者和消費(fèi)者問題

Condition實(shí)現(xiàn)精確通知喚醒

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題傳統(tǒng)Synchronized鎖定
實(shí)作一個(gè)基本的售票範(fàn)例:

/*
真正的多線程開發(fā),公司中的開發(fā),降低耦合性
線程就是一個(gè)單獨(dú)的資源類,沒有任何附屬的操作
1.屬性,方法
?*?*/public?class?SaleTicketDemo1?{
????public?static?void?main(String[]?args)?{
????????//并發(fā),多個(gè)線程操作同一個(gè)資源類,把資源類丟入線程
????????Ticket?ticket=new?Ticket();
????????//Runnable借口是一個(gè)FunationalInterface函數(shù)式接口,接口可以new,jdk1.8以后,lamda表達(dá)式()->{代碼}
????????new?Thread(()->{
????????????for(int?i=0;i{
????????????for(int?i=0;i0){
????????????System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩余"+number);
????????}
????}}

注意,這裡面用到了lambda表達(dá)式,lambda表達(dá)式詳細(xì)描述見Java基礎(chǔ)-Lambda表達(dá)式

# 這是使用傳統(tǒng)的synchronized實(shí)作並發(fā),
synchronized的本質(zhì)就是佇列,鎖定
。就好比食堂排隊(duì)。如果沒有排隊(duì),就會(huì)很亂。只有給一個(gè)人服務(wù)完成了,另一個(gè)人才能接收到服務(wù)。
Lock鎖定

之前已經(jīng)說道,JVM提供了synchronized關(guān)鍵字來實(shí)現(xiàn)對(duì)變數(shù)的同步存取以及用wait和notify來實(shí)現(xiàn)線程間通訊。在jdk1.5之後,JAVA提供了Lock類別來實(shí)現(xiàn)和synchronized一樣的功能,並且還提供了Condition來顯示線程間通訊。

Lock類別是Java類別來提供的功能,豐富的api使得Lock類別的同步功能比synchronized的同步更強(qiáng)大。 在java.util. ??Concurrent套件中,裡面有3個(gè)接口,Condition,lock(標(biāo)準(zhǔn)鎖定)。 ReadWriteLock鎖定(讀寫鎖定)

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題Lock實(shí)作提供比使用synchronized方法和語句可以獲得的更廣泛的鎖定操作。它們?cè)试S更靈活的結(jié)構(gòu)化,可能具有完全不同的屬性,並且可以支援多個(gè)相關(guān)聯(lián)的物件Condition。

Lock?l?=?...;?l.lock();?try?{?//?access?the?resource?protected?by?this?lock?}?finally?{?l.unlock();?}

lock()表示加鎖,unlock()表示解鎖
JDK官方文件中解釋

所有已知實(shí)作類別:

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題ReentrantLock可重入鎖定
ReentrantReadWriteLock.ReadLock 讀鎖定
ReentrantReadWriteLock.writeLock寫鎖

先說ReentrantLock實(shí)作類別: ReentrantLock底層原始碼建構(gòu)子

公平鎖定:十分公平,可以先來後到。但是問題如果一個(gè)3s和一個(gè)3h的進(jìn)程到達(dá),3h先,那麼3s等3h,實(shí)際上也不利。 非公平鎖:十分不公平,可以插隊(duì)(預(yù)設(shè))
之後,我們會(huì)具體解釋。

怎麼用,用之前加鎖,用之後解鎖

#//lock鎖三部曲

//1.new ReentranLock() ;建構(gòu)

//2.Lock.lock();加上鎖定
//3.finally();解鎖

#

public?class?SaleTicketDemo2?{
	public?static?void?main(String[]?args)?{
		//并發(fā),多個(gè)線程操作同一個(gè)資源類,把資源類丟入線程
		Ticket?ticket=new?Ticket();
		//Runnable借口是一個(gè)FunationalInterface函數(shù)式接口,接口可以new,jdk1.8以后,lamda表達(dá)式()->{代碼}
		new?Thread(()->{for(int?i=0;i{for(int?i=0;i{for(int?i=0;i0){
				System.out.println(Thread.currentThread().getName()+"賣出了"+(number--)+"票,剩余"+number);
			}
		}?catch?(Exception?e)?{
			//?TODO:?handle?exception
		}finally{
			lock.unlock();
		}	
	}}


Synchronized和lock鎖定的差別

1.synchronized是內(nèi)建的java關(guān)鍵字,lock是Java類別

2.synchronized無法判斷取得鎖定的狀態(tài),lock可以判斷是否取得到了鎖定 3.synchronized會(huì)自動(dòng)釋放鎖(a–),lock必須要手動(dòng)釋放鎖!如果不釋放鎖,會(huì)導(dǎo)致死鎖 4.Synchronized線程1(獲得鎖,阻塞),線程2(等待,傻傻的等)

lock.tryLock()嘗試獲取鎖,不一定會(huì)一直等下去

5.Synchronized可重入鎖,不可以中斷的,非公平鎖。 Lock,可重入鎖,可以判斷鎖,公平與非公平可以自行設(shè)定(可以自己設(shè)定)
6.synchronized適合少量的程式碼同步問題,lock鎖適合鎖大量的同步程式碼
synchornized鎖對(duì)象和同步程式碼區(qū)塊方法

傳統(tǒng)的生產(chǎn)者和消費(fèi)者問題


傳統(tǒng)的生產(chǎn)者和消費(fèi)者是基於Object類別的wait、notify方法和synchronized關(guān)鍵字來實(shí)現(xiàn)的。
在面試的時(shí)候,手寫生產(chǎn)者消費(fèi)者程式碼是很常見的事情。
面試筆試經(jīng)典問題:
單例模式排序演算法生產(chǎn)者消費(fèi)者死鎖
生產(chǎn)者消費(fèi)者問題synchronized版

線程之間的通訊問題:生產(chǎn)者和消費(fèi)者問題等待喚醒,通知喚醒

執(zhí)行緒交替執(zhí)行A B 操作同一個(gè)變數(shù)number=0Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題 A num 1
B num-1

## 注意:###加鎖的方法中,執(zhí)行的思路是判斷等待業(yè)務(wù)通知######
package?testConcurrent;/*
線程之間的通信問題:生產(chǎn)者和消費(fèi)者問題????等待喚醒,通知喚醒
線程交替執(zhí)行?A?B?操作同一個(gè)變量number=0
A?num+1
B?num-1

?*?*/public?class?A?{
	public?static?void?main(String[]?args)?{
		Data?data?=new?Data();
		new?Thread(()->{
			for(int?i=0;i{
			for(int?i=0;i"+number);
		//通知其他線程,我+1完畢了
		this.notify();
	}
	//-1
	public?synchronized?void?decrement()?throws?InterruptedException{
		if(number==0){
			//等待
			this.wait();
		}
		number--;
		System.out.println(Thread.currentThread().getName()+"=>"+number);
		//通知其他線程,我-1完畢了
		this.notify();
	}}
######### 如圖,基本上可以實(shí)現(xiàn)所要求的功能,但是這樣還會(huì)出現(xiàn)問題,如果此時(shí)我再加上了兩個(gè)線程,則###
		new?Thread(()->{
			for(int?i=0;i{
			for(int?i=0;i<p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/052/4011c6e510a595c0afc39326e031cf33-4.png" class="lazy" alt="Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題"><br> 這里結(jié)果中出現(xiàn)了2,輸出結(jié)果出現(xiàn)了問題。為什么呢?<br> 為什么if判斷會(huì)出現(xiàn)問題:<br> if判斷只判斷一次。因?yàn)閕f判斷了之后,就已經(jīng)進(jìn)入了代碼的等待那一行,這時(shí),在wait下的線程可能有多個(gè),甚至包括生產(chǎn)者和消費(fèi)者。有可能某個(gè)生產(chǎn)者執(zhí)行完了之后,喚醒的是另一個(gè)生產(chǎn)者。</p><p>在我們的官方文檔中就給出了解釋</p><pre class="brush:php;toolbar:false">public?final?void?wait(long?timeout)
????????????????throws?InterruptedException

導(dǎo)致當(dāng)前線程等待,直到另一個(gè)線程調(diào)用此對(duì)象的notify()方法或notifyAll()方法,或指定的時(shí)間已過。
線程也可以喚醒,而不會(huì)被通知,中斷或超時(shí),即所謂的虛假喚醒 。 雖然這在實(shí)踐中很少會(huì)發(fā)生,但應(yīng)用程序必須通過測(cè)試應(yīng)該使線程被喚醒的條件來防范,并且如果條件不滿足則繼續(xù)等待。 換句話說,等待應(yīng)該總是出現(xiàn)在循環(huán)中,就像這樣:

?synchronized?(obj)?{
?????????while?(<condition>)
?????????????obj.wait(timeout);
?????????...?//?Perform?action?appropriate?to?condition
?????}</condition>

注意點(diǎn):防止虛假喚醒問題。
我們代碼中用的是if判斷,而應(yīng)該用while判斷

package?testConcurrent;/*
線程之間的通信問題:生產(chǎn)者和消費(fèi)者問題????等待喚醒,通知喚醒
線程交替執(zhí)行?A?B?操作同一個(gè)變量number=0
A?num+1
B?num-1

?*?*/public?class?A?{
????public?static?void?main(String[]?args)?{
????????Data?data?=new?Data();
????????new?Thread(()->{
????????????for(int?i=0;i{
????????????for(int?i=0;i{
????????????for(int?i=0;i{
????????????for(int?i=0;i"+number);
????????//通知其他線程,我+1完畢了
????????this.notify();
????}
????//-1
????public?synchronized?void?decrement()?throws?InterruptedException{
????????while(number==0){
????????????//等待
????????????this.wait();
????????}
????????number--;
????????System.out.println(Thread.currentThread().getName()+"=>"+number);
????????//通知其他線程,我-1完畢了
????????this.notify();
????}}

Lock版的生產(chǎn)者和消費(fèi)者問題

在synchronized版本中,我們使用了wait和notify來實(shí)現(xiàn)線程之間的同步
在lock中,
此時(shí)synchronized被lock替換了,那么wait和notify用什么來替換呢?
我們?cè)诠俜轿臋njava.util.concurrent.locks 中,找到Lock類,然后在底部找到了
Condition newCondition()
返回一個(gè)新Condition綁定到該實(shí)例Lock實(shí)例。
在等待條件之前,鎖必須由當(dāng)前線程保持。 呼叫Condition.await()將在等待之前將原子釋放鎖,并在等待返回之前重新獲取鎖。

然后我們?cè)賮砹私釩ondition類
Condition 將 Object 監(jiān)視器方法(wait、notify 和 notifyAll)分解成截然不同的對(duì)象,以便通過將這些對(duì)象與任意 Lock 實(shí)現(xiàn)組合使用,為每個(gè)對(duì)象提供多個(gè)等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監(jiān)視器方法的使用。
一個(gè)Condition實(shí)例本質(zhì)上綁定到一個(gè)鎖。 要獲得特定Condition實(shí)例的Condition實(shí)例,請(qǐng)使用其newCondition()方法。

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題
我們可以看到,使用的時(shí)候new一個(gè)Condition對(duì)象。然后用await替代wait,signal替換notify
代碼實(shí)現(xiàn)
//判斷等待+業(yè)務(wù)+通知

class?Data2{		//數(shù)字。資源類
	private?int?number=0;
	Lock?lock=new?ReentrantLock();
	Condition?condition=lock.newCondition();
	//+1
	public?void?increment()?throws?InterruptedException{
		try?{
			lock.lock();
			//業(yè)務(wù)代碼
			while(number!=0){		
				//等待
				condition.await();
			}
			number++;		
			System.out.println(Thread.currentThread().getName()+"=>"+number);
			condition.signalAll();		//通知
		}?catch?(Exception?e)?{
			//?TODO:?handle?exception
		}finally{
			lock.unlock();
		}
	}
	//-1
	public?void?decrement()?throws?InterruptedException{
		try?{
			lock.lock();
			//業(yè)務(wù)代碼
			while(number!=1){		
				//等待
				condition.await();
			}
			number--;		
			System.out.println(Thread.currentThread().getName()+"=>"+number);
			condition.signalAll();		//通知
		}?catch?(Exception?e)?{
			//?TODO:?handle?exception
		}finally{
			lock.unlock();
		}
	}	}

注意:主函數(shù)部分于最上面的代碼一樣。

Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題
這時(shí)候雖然說是正確的,但是它是一個(gè)隨機(jī)分布的狀態(tài),現(xiàn)在我們希望它有序執(zhí)行,即A執(zhí)行完了執(zhí)行B,B執(zhí)行C,C完了執(zhí)行D。即精準(zhǔn)通知。

Condition實(shí)現(xiàn)精準(zhǔn)通知喚醒

Condition實(shí)現(xiàn)精準(zhǔn)的通知和喚醒
我們構(gòu)造三個(gè)線程,要求A執(zhí)行完了執(zhí)行B,B執(zhí)行完了執(zhí)行C,C執(zhí)行完了執(zhí)行D.
代碼思想:
//加多個(gè)監(jiān)視器,通過監(jiān)視器來判斷喚醒的是哪一個(gè)人
//設(shè)置多個(gè)同步監(jiān)視器,每個(gè)監(jiān)視器監(jiān)視一個(gè)線程
//實(shí)例:生產(chǎn)線,下單->支付->交易->物流

package?testConcurrent;import?java.util.concurrent.locks.Condition;import?java.util.concurrent.locks.Lock;import?java.util.concurrent.locks.ReentrantLock;/*
A執(zhí)行完調(diào)用B,B執(zhí)行完調(diào)用C,C執(zhí)行完調(diào)用A
?*?*/public?class?C?{

????public?static?void?main(String[]?args)?{
????????Data3?data=new?Data3();
????????new?Thread(()->{
????????????for(int?i=0;i{
????????????for(int?i=0;i{
????????????for(int?i=0;i支付->交易->物流
????private?Condition?condition1=lock.newCondition();
????private?Condition?condition2=lock.newCondition();
????private?Condition?condition3=lock.newCondition();
????private?int?number=1;???????//1A?2B?3C
????public?void?printA(){
????????lock.lock();
????????try?{
????????????//業(yè)務(wù),判斷->執(zhí)行->通知
????????????while(number!=1){
????????????????//等待
????????????????condition1.await();
????????????}
????????????System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
????????????//喚醒,喚醒指定的人,B
????????????number=2;???????????//精準(zhǔn)喚醒
????????????condition2.signal();
????????????
????????}?catch?(Exception?e)?{
????????????//?TODO:?handle?exception
????????}finally{
????????????lock.unlock();
????????}
????}???
????public?void?printB(){
????????lock.lock();
????????try?{
????????????//業(yè)務(wù),判斷->執(zhí)行->通知
????????????while(number!=2){
????????????????//等待
????????????????condition2.await();
????????????}
????????????System.out.println(Thread.currentThread().getName()+"=>BBBBBBB");
????????????//喚醒,喚醒指定的人,C
????????????number=3;???????????//精準(zhǔn)喚醒
????????????condition3.signal();
????????????
????????}?catch?(Exception?e)?{
????????????//?TODO:?handle?exception
????????}finally{
????????????lock.unlock();
????????}
????}
????public?void?printC(){
????????lock.lock();
????????try?{
????????????//業(yè)務(wù),判斷->執(zhí)行->通知
????????????while(number!=3){
????????????????//等待
????????????????condition3.await();
????????????}
????????????System.out.println(Thread.currentThread().getName()+"=>CCCCCCC");
????????????//喚醒,喚醒指定的人,A
????????????number=1;???????????//精準(zhǔn)喚醒
????????????condition1.signal();
????????????
????????}?catch?(Exception?e)?{
????????????//?TODO:?handle?exception
????????}finally{
????????????lock.unlock();
????????}
????}}

相關(guān)學(xué)習(xí)推薦:java基礎(chǔ)

以上是Java介紹Lock鎖與生產(chǎn)者消費(fèi)者問題的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門話題

Laravel 教程
1597
29
PHP教程
1488
72
VSCODE設(shè)置。 JSON位置 VSCODE設(shè)置。 JSON位置 Aug 01, 2025 am 06:12 AM

settings.json文件位於用戶級(jí)或工作區(qū)級(jí)路徑,用於自定義VSCode設(shè)置。 1.用戶級(jí)路徑:Windows為C:\Users\\AppData\Roaming\Code\User\settings.json,macOS為/Users//Library/ApplicationSupport/Code/User/settings.json,Linux為/home//.config/Code/User/settings.json;2.工作區(qū)級(jí)路徑:項(xiàng)目根目錄下的.vscode/settings

如何使用JDBC處理Java的交易? 如何使用JDBC處理Java的交易? Aug 02, 2025 pm 12:29 PM

要正確處理JDBC事務(wù),必須先關(guān)閉自動(dòng)提交模式,再執(zhí)行多個(gè)操作,最後根據(jù)結(jié)果提交或回滾;1.調(diào)用conn.setAutoCommit(false)以開始事務(wù);2.執(zhí)行多個(gè)SQL操作,如INSERT和UPDATE;3.若所有操作成功則調(diào)用conn.commit(),若發(fā)生異常則調(diào)用conn.rollback()確保數(shù)據(jù)一致性;同時(shí)應(yīng)使用try-with-resources管理資源,妥善處理異常並關(guān)閉連接,避免連接洩漏;此外建議使用連接池、設(shè)置保存點(diǎn)實(shí)現(xiàn)部分回滾,並保持事務(wù)盡可能短以提升性能。

在Java的掌握依賴注入春季和Guice 在Java的掌握依賴注入春季和Guice Aug 01, 2025 am 05:53 AM

依賴性(di)IsadesignpatternwhereObjectsReceivedenciesenciesExtern上,推廣looseSecouplingAndEaseerTestingThroughConstructor,setter,orfieldInjection.2.springfraMefringframeWorkSannotationsLikeLikeLike@component@component,@component,@service,@autowiredwithjava-service和@autowiredwithjava-ligatiredwithjava-lase-lightike

Python Itertools組合示例 Python Itertools組合示例 Jul 31, 2025 am 09:53 AM

itertools.combinations用於生成從可迭代對(duì)像中選取指定數(shù)量元素的所有不重複組合(順序無關(guān)),其用法包括:1.從列表中選2個(gè)元素組合,如('A','B')、('A','C')等,避免重複順序;2.對(duì)字符串取3個(gè)字符組合,如"abc"、"abd",適用於子序列生成;3.求兩數(shù)之和等於目標(biāo)值的組合,如1 5=6,簡(jiǎn)化雙重循環(huán)邏輯;組合與排列的區(qū)別在於順序是否重要,combinations視AB與BA為相同,而permutations視為不同;

了解Java虛擬機(jī)(JVM)內(nèi)部 了解Java虛擬機(jī)(JVM)內(nèi)部 Aug 01, 2025 am 06:31 AM

TheJVMenablesJava’s"writeonce,runanywhere"capabilitybyexecutingbytecodethroughfourmaincomponents:1.TheClassLoaderSubsystemloads,links,andinitializes.classfilesusingbootstrap,extension,andapplicationclassloaders,ensuringsecureandlazyclassloa

如何使用Java的日曆? 如何使用Java的日曆? Aug 02, 2025 am 02:38 AM

使用java.time包中的類替代舊的Date和Calendar類;2.通過LocalDate、LocalDateTime和LocalTime獲取當(dāng)前日期時(shí)間;3.使用of()方法創(chuàng)建特定日期時(shí)間;4.利用plus/minus方法不可變地增減時(shí)間;5.使用ZonedDateTime和ZoneId處理時(shí)區(qū);6.通過DateTimeFormatter格式化和解析日期字符串;7.必要時(shí)通過Instant與舊日期類型兼容;現(xiàn)代Java中日期處理應(yīng)優(yōu)先使用java.timeAPI,它提供了清晰、不可變且線

Google Chrome無法打開本地文件 Google Chrome無法打開本地文件 Aug 01, 2025 am 05:24 AM

ChromecanopenlocalfileslikeHTMLandPDFsbyusing"Openfile"ordraggingthemintothebrowser;ensuretheaddressstartswithfile:///;2.SecurityrestrictionsblockAJAX,localStorage,andcross-folderaccessonfile://;usealocalserverlikepython-mhttp.server8000tor

如何使用Prometheus和Grafana監(jiān)視Java應(yīng)用程序 如何使用Prometheus和Grafana監(jiān)視Java應(yīng)用程序 Jul 31, 2025 am 09:42 AM

TomonitoraJavaapplicationwithPrometheusandGrafana,firstinstrumenttheappusingMicrometerbyaddingmicrometer-registry-prometheusandSpringBootActuatordependencies,thenexposethe/actuator/prometheusendpointviaconfigurationinapplication.yml.2.SetupPrometheus

See all articles