Java 多線程Synchronized和Lock的區(qū)別
引言
在多線程中,為了使線程安全,我們經(jīng)常會(huì)使用synchronized和Lock進(jìn)行代碼同步和加鎖,但是具體兩者有什么區(qū)別,什么場(chǎng)景下適合用什么可能還不大清楚,主要的區(qū)別大致如下:
區(qū)別
1、synchronized是java關(guān)鍵字,而Lock是java中的一個(gè)接口
2、synchronized會(huì)自動(dòng)釋放鎖,而Lock必須手動(dòng)釋放鎖
3、synchronized是不可中斷的,Lock可以中斷也可以不中斷
4、通過(guò)Lock可以知道線程有沒(méi)有拿到鎖,而synchronized不能
5、synchronized能鎖住方法和代碼塊,而Lock只能鎖住代碼塊
6、Lock可以使用讀鎖提高多線程讀效率
7、synchronized是非公平鎖,ReentranLock可以控制是否公平鎖
從Lock接口中我們可以看到主要有5個(gè)方法,這些方法的功能從注釋中可以看出:
lock():獲取鎖,如果鎖被暫用則一直等待 unlock():釋放鎖 tryLock(): 注意返回類(lèi)型是boolean,如果獲取鎖的時(shí)候鎖被占用就返回false,否則返回true tryLock(long time, TimeUnit unit):比起tryLock()就是給了一個(gè)時(shí)間期限,保證等待參數(shù)時(shí)間 lockInterruptibly():用該鎖的獲得方式,如果線程在獲取鎖的階段進(jìn)入了等待,那么可以中斷此線程,先去做別的事 通過(guò) 以上的解釋?zhuān)笾驴梢越忉屧谏蟼€(gè)部分中“鎖類(lèi)型(lockInterruptibly())”,“鎖狀態(tài)(tryLock())”等問(wèn)題,還有就是前面子所獲取的過(guò)程我所寫(xiě)的“大致就是可以嘗試獲得鎖,線程可以不會(huì)一直等待”用了“可以”的原因。
lock():
public class LockTest { private Lock lock = new ReentrantLock(); private void method(Thread thread) { lock.lock(); try { System.out.println(thread.getName() + " has gotten the lock!"); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println(thread.getName() + " has unlocked the lock!"); lock.unlock(); } } public static void main(String[] args) { final LockTest test = new LockTest(); Thread t1 = new Thread(new Runnable() { @Override public void run() { test.method(Thread.currentThread()); } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { test.method(Thread.currentThread()); } }, "t2"); t1.start(); t2.start(); } }
運(yùn)行結(jié)果:
t1 has gotten the lock! t1 has unlocked the lock! t2 has gotten the lock! t2 has unlocked the lock!
tryLock():
public class LockTest { private Lock lock = new ReentrantLock(); private void method(Thread thread) { if (lock.tryLock()) { lock.lock(); try { System.out.println(thread.getName() + " has gotten the lock!"); } catch (Exception e) { e.printStackTrace(); } finally { System.out.println(thread.getName() + " has unlocked the lock!"); lock.unlock(); } } else { System.out.println("I'm "+thread.getName()+". Someone has gotten the lock!"); } } public static void main(String[] args) { LockTest test = new LockTest(); Thread t1 = new Thread(() -> test.method(Thread.currentThread()), "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { test.method(Thread.currentThread()); } }, "t2"); t1.start(); t2.start(); } }
運(yùn)行結(jié)果:
t1 has gotten the lock! t1 has unlocked the lock! I'm t2. Someone has gotten the lock!
看到這里相信大家也都會(huì)使用如何使用Lock了吧,關(guān)于tryLock(long time, TimeUnit unit)和lockInterruptibly()不再贅述。前者主要存在一個(gè)等待時(shí)間,在測(cè)試代碼中寫(xiě)入一個(gè)等待時(shí)間,后者主要是等待中斷,會(huì)拋出一個(gè)中斷異常,常用度不高,喜歡探究可以自己深入研究。
以上就是Java 多線程Synchronized和Lock的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Java 多線程Synchronized和Lock的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot項(xiàng)目中自定義Banner的技術(shù)指南
在 Spring Boot 項(xiàng)目中,當(dāng)應(yīng)用啟動(dòng)時(shí)會(huì)顯示默認(rèn)的 Spring 標(biāo)志和版本信息,定制化的啟動(dòng) Banner 不僅可以美化應(yīng)用,甚至可以提供一些關(guān)鍵信息,本文將介紹如何在 Spring Boot 項(xiàng)目中自定義啟動(dòng) Banner,需要的朋友可以參考下2025-03-03基于Spring AMQP實(shí)現(xiàn)消息隊(duì)列的示例代碼
Spring AMQP作為Spring框架的一部分,是一套用于支持高級(jí)消息隊(duì)列協(xié)議(AMQP)的工具,AMQP是一種強(qiáng)大的消息協(xié)議,旨在支持可靠的消息傳遞,本文給大家介紹了如何基于Spring AMQP實(shí)現(xiàn)消息隊(duì)列,需要的朋友可以參考下2024-03-03將ResultSet中得到的一行或多行結(jié)果集封裝成對(duì)象的實(shí)例
這篇文章主要介紹了將ResultSet中得到的一行或多行結(jié)果集封裝成對(duì)象的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05Java實(shí)現(xiàn)人臉識(shí)別登錄、注冊(cè)等功能(最新完整版)
這段時(shí)間由于學(xué)校實(shí)行靜態(tài)化管理,寢室門(mén)和校門(mén)都是用了人臉識(shí)別的裝置,本系列項(xiàng)目從設(shè)計(jì)到實(shí)現(xiàn)源碼全部開(kāi)源免費(fèi)學(xué)習(xí)使用,對(duì)Java實(shí)現(xiàn)人臉識(shí)別登錄、注冊(cè)功能感興趣的朋友一起看看吧2022-05-05Springboot中@Async異步,實(shí)現(xiàn)異步結(jié)果合并統(tǒng)一返回方式
這篇文章主要介紹了Springboot中@Async異步,實(shí)現(xiàn)異步結(jié)果合并統(tǒng)一返回方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09Java8新特性之Collectors.joining()實(shí)例詳解
在項(xiàng)目中我們常常要對(duì)list集合的數(shù)據(jù)做一些字符串拼接/處理等相關(guān)操作,下面這篇文章主要給大家介紹了關(guān)于Java8新特性之Collectors.joining()的相關(guān)資料,需要的朋友可以參考下2023-01-01SpringBoot 下在 yml 中的 logging 日志配置方法
logging 配置主要用于控制應(yīng)用程序的日志輸出行為,可以通過(guò)配置定制日志的格式、級(jí)別、輸出位置等,這篇文章主要介紹了SpringBoot 下在 yml 中的 logging 日志配置,需要的朋友可以參考下2024-06-06SpringBoot使用AOP+注解實(shí)現(xiàn)簡(jiǎn)單的權(quán)限驗(yàn)證的方法
這篇文章主要介紹了SpringBoot使用AOP+注解實(shí)現(xiàn)簡(jiǎn)單的權(quán)限驗(yàn)證的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05java多線程編程之使用runnable接口創(chuàng)建線程
實(shí)現(xiàn)Runnable接口的類(lèi)必須使用Thread類(lèi)的實(shí)例才能創(chuàng)建線程,通過(guò)Runnable接口創(chuàng)建線程分為以下兩步2014-01-01