Java并發(fā)系列之JUC中的Lock鎖與synchronized同步代碼塊問題
寫在前邊: 在Java服務(wù)端中,會常常遇到并發(fā)的場景,以下我使用兩個售票的案例實現(xiàn)傳統(tǒng)的Lock鎖與synchronized加鎖解決線程安全問題。
本章代碼:Gitee: juc.demo
一、Lock鎖
ReentrantLock
類: 可重用鎖(公平鎖|非公平鎖)ReentrantReadWriteLock.ReadLock
:讀鎖ReentrantReadWriteLock.WriteLock
:寫鎖
二、鎖的底層
鎖的底層有公平鎖和非公平鎖。其中:
- 公平鎖 :十分公平,不能插隊。
- 非公平鎖 :十分不公平,可以插隊。(默認非公平鎖)
三、案例
案例一:傳統(tǒng)的synchronized實現(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ì): 隊列,鎖 public synchronized void sale(){ if (num > 0){ System.out.println(Thread.currentThread().getName()+"賣出了"+(num--)+"票,剩余:"+num); } }
案例二:Lock鎖的實現(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(){ // 可重入鎖 默認:非公平鎖:十分不公平,可以插隊。(默認非公平鎖) 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
是一個Java類。synchronized
無法判斷獲取鎖的狀態(tài);Lock
可以判斷是否獲取到了鎖。(boolean b = lock.tryLock();)synchronized
會自動釋放鎖;Lock
必須要手動釋放鎖,如果不釋放鎖,死鎖。synchronized
線程1獲得鎖阻塞時,線程2會一直等待下去;Lock鎖線程1獲得鎖阻塞時,線程2等待足夠長的時間后中斷等待,去做其他的事。synchronized
可重入鎖:不可以中斷的,非公平;Lock可重入鎖:可以判斷鎖,非公平(可以自己設(shè)置)。lock.lockInterruptibly()
;方法:當兩個線程同時通過該方法想獲取某個鎖時,假若此時線程A獲取到了鎖,而線程B只有在等待,那么對線程B調(diào)用threadB.interrupt()
方法能夠中斷線程B的等待過程。synchronized
適合鎖少量的代碼同步問題; Lock適合鎖大量的同步代碼。
到此這篇關(guān)于Java并發(fā)系列之JUC中的Lock鎖與synchronized同步代碼塊的文章就介紹到這了,更多相關(guān)Java synchronized同步代碼塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
教你在一分鐘之內(nèi)理解Java Lambda表達式并學會使用
今天給大家?guī)У奈恼率荍ava8新特性的相關(guān)知識,文章圍繞著如何在一分鐘之內(nèi)理解Java Lambda表達式并學會使用展開,文中有非常詳細的介紹,需要的朋友可以參考下2021-06-06解決@ConfigurationProperties注解的使用及亂碼問題
這篇文章主要介紹了解決@ConfigurationProperties注解的使用及亂碼問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10SpringBoot采用AJAX實現(xiàn)異步發(fā)布帖子詳解
Ajax是一種web應(yīng)用技術(shù),可以借助客戶端腳本(javascript)與服務(wù)端應(yīng)用進行異步通訊,獲取服務(wù)端數(shù)據(jù)以后,可以進行局部刷新,進而提高數(shù)據(jù)的響應(yīng)和渲染速度。所有的Ajax請求都會基于DOM(HTML元素)事件,通過XHR(XMLHttpRequest)對象實現(xiàn)與服務(wù)端異步通訊局部更新2022-08-08java 通過cmd 調(diào)用命令啟動tomcat的操作
這篇文章主要介紹了java 通過cmd 調(diào)用命令啟動tomcat的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11