Java并發(fā)系列之JUC中的Lock鎖與synchronized同步代碼塊問題
寫在前邊: 在Java服務(wù)端中,會(huì)常常遇到并發(fā)的場景,以下我使用兩個(gè)售票的案例實(shí)現(xiàn)傳統(tǒng)的Lock鎖與synchronized加鎖解決線程安全問題。
本章代碼:Gitee: juc.demo
一、Lock鎖
ReentrantLock類: 可重用鎖(公平鎖|非公平鎖)ReentrantReadWriteLock.ReadLock:讀鎖ReentrantReadWriteLock.WriteLock:寫鎖
二、鎖的底層
鎖的底層有公平鎖和非公平鎖。其中:
- 公平鎖 :十分公平,不能插隊(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無法判斷獲取鎖的狀態(tài);Lock可以判斷是否獲取到了鎖。(boolean b = lock.tryLock();)synchronized會(huì)自動(dòng)釋放鎖;Lock必須要手動(dòng)釋放鎖,如果不釋放鎖,死鎖。synchronized線程1獲得鎖阻塞時(shí),線程2會(huì)一直等待下去;Lock鎖線程1獲得鎖阻塞時(shí),線程2等待足夠長的時(shí)間后中斷等待,去做其他的事。synchronized可重入鎖:不可以中斷的,非公平;Lock可重入鎖:可以判斷鎖,非公平(可以自己設(shè)置)。lock.lockInterruptibly();方法:當(dāng)兩個(gè)線程同時(shí)通過該方法想獲取某個(gè)鎖時(shí),假若此時(shí)線程A獲取到了鎖,而線程B只有在等待,那么對(duì)線程B調(diào)用threadB.interrupt()方法能夠中斷線程B的等待過程。synchronized適合鎖少量的代碼同步問題; 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ì)使用展開,文中有非常詳細(xì)的介紹,需要的朋友可以參考下2021-06-06
解決@ConfigurationProperties注解的使用及亂碼問題
這篇文章主要介紹了解決@ConfigurationProperties注解的使用及亂碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
SpringBoot采用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元素)事件,通過XHR(XMLHttpRequest)對(duì)象實(shí)現(xiàn)與服務(wù)端異步通訊局部更新2022-08-08
Java 如何從spring容器中獲取注入的bean對(duì)象
這篇文章主要介紹了Java 如何從spring容器中獲取注入的bean對(duì)象,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-11-11
java與C 代碼運(yùn)行效率的對(duì)比(整理)
最近和朋友無意間討論起了 有關(guān)java 和C 的 效率問題, (我是java 推介者, 他是 c 語言推介者, 他做的是嵌入式)故,想通過網(wǎng)絡(luò)查詢一下, 總結(jié)一下,兩者到底效率如何,其有何差異,原因又是啥?各種優(yōu)勢有在何處?2021-04-04
java 通過cmd 調(diào)用命令啟動(dòng)tomcat的操作
這篇文章主要介紹了java 通過cmd 調(diào)用命令啟動(dòng)tomcat的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11
Java連接MYSQL數(shù)據(jù)庫的詳細(xì)步驟
這篇文章主要為大家介紹了Java連接MYSQL數(shù)據(jù)庫的詳細(xì)步驟,感興趣的小伙伴們可以參考一下2016-05-05
mybatis對(duì)傳入基本類型參數(shù)的判斷方式
這篇文章主要介紹了mybatis對(duì)傳入基本類型參數(shù)的判斷方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03

