Java并發(fā)系列之JUC中的Lock鎖與synchronized同步代碼塊問(wèn)題
寫(xiě)在前邊: 在Java服務(wù)端中,會(huì)常常遇到并發(fā)的場(chǎng)景,以下我使用兩個(gè)售票的案例實(shí)現(xiàn)傳統(tǒng)的Lock鎖與synchronized加鎖解決線程安全問(wèn)題。
本章代碼:Gitee: juc.demo
一、Lock鎖
ReentrantLock
類: 可重用鎖(公平鎖|非公平鎖)ReentrantReadWriteLock.ReadLock
:讀鎖ReentrantReadWriteLock.WriteLock
:寫(xiě)鎖
二、鎖的底層
鎖的底層有公平鎖和非公平鎖。其中:
- 公平鎖 :十分公平,不能插隊(duì)。
- 非公平鎖 :十分不公平,可以插隊(duì)。(默認(rèn)非公平鎖)
三、案例
案例一:傳統(tǒng)的synchronized實(shí)現(xiàn)
/** * synchronized 同步代碼塊保證售票線程安全 * * @Author JUNSHI * @Create 2022-04-10 22:46 */ public class SaleTicketDemo01 { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(()->{ for (int i = 0; i < 60; i++) { ticket.sale(); } },"AA").start(); },"BB").start(); new Thread(() -> { }, "CC").start(); } static class Ticket{ // 50張飄票 private int num = 50; // 售票 synchronized(同步代碼塊) 本質(zhì): 隊(duì)列,鎖 public synchronized void sale(){ if (num > 0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(num--)+"票,剩余:"+num); } }
案例二:Lock鎖的實(shí)現(xiàn)
/** * Lock 加鎖保證售票線程安全 * * @Author JUNSHI * @Create 2022-04-10 22:46 */ public class SaleTicketDemo02 { public static void main(String[] args) { Ticket2 ticket = new Ticket2(); new Thread(()->{ for (int i = 0; i < 60; i++) ticket.sale(); },"AA").start(); new Thread(()->{ for (int i = 0; i < 60; i++) ticket.sale(); },"BB").start(); new Thread(()->{ for (int i = 0; i < 60; i++) ticket.sale(); },"CC").start(); } static class Ticket2{ // 50張飄票 private int num = 50; // 加鎖三部曲 // 1、 創(chuàng)建鎖 => new ReentrantLock(); // 2、 加鎖 => lock.lock(); // 3、 釋放鎖 => lock.unlock(); public void sale(){ // 可重入鎖 默認(rèn):非公平鎖:十分不公平,可以插隊(duì)。(默認(rèn)非公平鎖) Lock lock = new ReentrantLock(); // 加鎖 lock.lock(); try { // 執(zhí)行業(yè)務(wù) if (num > 0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(num--)+"票,剩余:"+num); } } catch (Exception e) { e.printStackTrace(); } finally { // 解鎖 lock.unlock(); } } } }
四、Lock鎖和synchronized的區(qū)別
snchronized
是內(nèi)置Java關(guān)鍵字;Lock
是一個(gè)Java類。synchronized
無(wú)法判斷獲取鎖的狀態(tài);Lock
可以判斷是否獲取到了鎖。(boolean b = lock.tryLock();)synchronized
會(huì)自動(dòng)釋放鎖;Lock
必須要手動(dòng)釋放鎖,如果不釋放鎖,死鎖。synchronized
線程1獲得鎖阻塞時(shí),線程2會(huì)一直等待下去;Lock鎖線程1獲得鎖阻塞時(shí),線程2等待足夠長(zhǎng)的時(shí)間后中斷等待,去做其他的事。synchronized
可重入鎖:不可以中斷的,非公平;Lock可重入鎖:可以判斷鎖,非公平(可以自己設(shè)置)。lock.lockInterruptibly()
;方法:當(dāng)兩個(gè)線程同時(shí)通過(guò)該方法想獲取某個(gè)鎖時(shí),假若此時(shí)線程A獲取到了鎖,而線程B只有在等待,那么對(duì)線程B調(diào)用threadB.interrupt()
方法能夠中斷線程B的等待過(guò)程。synchronized
適合鎖少量的代碼同步問(wèn)題; Lock適合鎖大量的同步代碼。
到此這篇關(guān)于Java并發(fā)系列之JUC中的Lock鎖與synchronized同步代碼塊的文章就介紹到這了,更多相關(guān)Java synchronized同步代碼塊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
教你在一分鐘之內(nèi)理解Java Lambda表達(dá)式并學(xué)會(huì)使用
今天給大家?guī)У奈恼率荍ava8新特性的相關(guān)知識(shí),文章圍繞著如何在一分鐘之內(nèi)理解Java Lambda表達(dá)式并學(xué)會(huì)使用展開(kāi),文中有非常詳細(xì)的介紹,需要的朋友可以參考下2021-06-06解決@ConfigurationProperties注解的使用及亂碼問(wèn)題
這篇文章主要介紹了解決@ConfigurationProperties注解的使用及亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10SpringBoot采用AJAX實(shí)現(xiàn)異步發(fā)布帖子詳解
Ajax是一種web應(yīng)用技術(shù),可以借助客戶端腳本(javascript)與服務(wù)端應(yīng)用進(jìn)行異步通訊,獲取服務(wù)端數(shù)據(jù)以后,可以進(jìn)行局部刷新,進(jìn)而提高數(shù)據(jù)的響應(yīng)和渲染速度。所有的Ajax請(qǐng)求都會(huì)基于DOM(HTML元素)事件,通過(guò)XHR(XMLHttpRequest)對(duì)象實(shí)現(xiàn)與服務(wù)端異步通訊局部更新2022-08-08Java 如何從spring容器中獲取注入的bean對(duì)象
這篇文章主要介紹了Java 如何從spring容器中獲取注入的bean對(duì)象,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-11-11java與C 代碼運(yùn)行效率的對(duì)比(整理)
最近和朋友無(wú)意間討論起了 有關(guān)java 和C 的 效率問(wèn)題, (我是java 推介者, 他是 c 語(yǔ)言推介者, 他做的是嵌入式)故,想通過(guò)網(wǎng)絡(luò)查詢一下, 總結(jié)一下,兩者到底效率如何,其有何差異,原因又是啥?各種優(yōu)勢(shì)有在何處?2021-04-04java 通過(guò)cmd 調(diào)用命令啟動(dòng)tomcat的操作
這篇文章主要介紹了java 通過(guò)cmd 調(diào)用命令啟動(dòng)tomcat的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11Java連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟
這篇文章主要為大家介紹了Java連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟,感興趣的小伙伴們可以參考一下2016-05-05mybatis對(duì)傳入基本類型參數(shù)的判斷方式
這篇文章主要介紹了mybatis對(duì)傳入基本類型參數(shù)的判斷方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03