Java synchronized關(guān)鍵字和Lock接口實現(xiàn)原理
這篇文章主要介紹了Java synchronized關(guān)鍵字和Lock接口實現(xiàn)原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
引用
當開發(fā)過程中,我們遇到并發(fā)問題。怎么解決?
一種解決方式,簡單粗暴:上鎖。將千軍萬馬都給攔下來,只允許一個人過獨木橋。書面意思就是將并行的程序變成串行的程序?,F(xiàn)實的鎖有門鎖、掛鎖和抽屜鎖等等。在Java中,我們的鎖就是synchronized關(guān)鍵字和Lock接口。
synchronized關(guān)鍵字
synchronized也叫同步鎖,是Java里面的關(guān)鍵字。我們可以猜測到synchronized原理也JVM虛擬機有關(guān)聯(lián)。
synchronized鎖的是對象。對象里面有一個叫做監(jiān)視鎖(monitor)的東西,監(jiān)視鎖依賴操作系統(tǒng)的互斥鎖(Mutex Lock)。操作系統(tǒng)切換線程其實就是從用戶態(tài)編程核心態(tài)(cpu的兩種狀態(tài))。這個代價有點高,所以synchronized這個重量級鎖后面也引進了偏向鎖和輕量級鎖。
加鎖(監(jiān)視鎖monitor)過程分析():
- 當monitor的進入數(shù)為0,線程A進入
- monitor的進入數(shù)為1
- 線程B想進入該monitor就會被阻塞。
線程A可以重復(fù)進入該monitor,所以synchronized是可重入鎖,和Lock實現(xiàn)的鎖一樣。
程序驗證
public class SynchronizedTest { private static int i = 0; public static void main(String[] args) { test(); } public static void test(){ synchronized (SynchronizedTest.class){ synchronized (SynchronizedTest.class){ i++; } } } }
運行結(jié)果
程序正常運行,沒有報錯
synchronized可以修飾方法以及代碼塊,代碼塊就是上面重入鎖的例子。
修飾方法
public class SynchronizedTest { static int n = 100; final static CountDownLatch start = new CountDownLatch(n); private static int i = 0; public static void main(String[] args) throws InterruptedException { for (int j = 0; j < n; j++) { Thread thread = new Thread(new addNoSynchronized()); thread.start(); } start.await(); System.out.println(i); } public static class addSynchronized implements Runnable{ @Override public void run() { addSynchronized(); } public static synchronized void addSynchronized(){ for (int j = 0; j < 1000; j++) { i++; } start.countDown(); } } }
運行結(jié)果
100000
如果去掉 synchronized 關(guān)鍵字的話,運行結(jié)果大概率不是 100000,因為線程不安全問題。
Lock接口
一般我們使用 ReentrantLock 類作為重入鎖,實現(xiàn)Lock接口。
使用方法
public class ReentranLockTest { private static int j; private static int n = 100; private static CountDownLatch latch = new CountDownLatch(n); public static void main(String[] args) throws InterruptedException { for (int i = 0; i < n; i++) { new Thread(new LockTest()).start(); } latch.await(); System.out.println("結(jié)果為:"+j); } public static class LockTest implements Runnable{ static Lock lock = new ReentrantLock(); @Override public void run() { lockTest(); latch.countDown(); } private void lockTest() { lock.lock(); try { for (int i = 0; i < 1000; i++) { j++; } }finally { lock.unlock(); } } } }
運行結(jié)果
結(jié)果為:100000
這里我們鎖住的 j++ 這塊資源區(qū)(公共資源),lock 是 static 關(guān)鍵字修飾的,是類對象,思考一下如果不是類對象會怎么樣?那就是連環(huán)鎖了(看圖)。
每一個線程都對可以用鑰匙解開這把鎖,對于程序而言,加鎖操作就沒有意義了。因為我們需要的是一個鎖。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- java中synchronized Lock(本地同步)鎖的8種情況
- 詳解Java中的鎖Lock和synchronized
- Java 多線程Synchronized和Lock的區(qū)別
- Java線程安全解決方案(synchronized,ReentrantLock,Atomic)
- 深入理解java內(nèi)置鎖(synchronized)和顯式鎖(ReentrantLock)
- Java編程synchronized與lock的區(qū)別【推薦】
- 深入Synchronized和java.util.concurrent.locks.Lock的區(qū)別詳解
- Java中提供synchronized后為什么還要提供Lock
相關(guān)文章
SpringBoot集成企業(yè)微信開發(fā)的實現(xiàn)
本文將詳細介紹如何使用?Spring?Boot?集成企業(yè)微信開發(fā),通過企業(yè)微信?API?可以實現(xiàn)企業(yè)內(nèi)部的一些自動化業(yè)務(wù)流程,提高工作效率,感興趣的可以了解一下2023-07-07如何利用Spring把元素解析成BeanDefinition對象
這篇文章主要介紹了如何利用Spring把元素解析成BeanDefinition對象,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08淺談java String.split丟失結(jié)尾空字符串的問題
下面小編就為大家?guī)硪黄獪\談java String.split丟失結(jié)尾空字符串的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02SpringBoot使用@PathVariable進行數(shù)據(jù)校驗的流程步驟
在SpringBoot項目中,我們經(jīng)常需要從 URL 中獲取參數(shù)并進行相關(guān)的數(shù)據(jù)校驗,而@PathVariable注解就是一種非常方便的方式,可以讓我們在方法參數(shù)中直接獲取URL中的參數(shù),并進行數(shù)據(jù)校驗,本文將介紹如何使用@PathVariable注解進行數(shù)據(jù)校驗2023-06-06spring boot starter actuator(健康監(jiān)控)配置和使用教程
這篇文章主要介紹了spring-boot-starter-actuator(健康監(jiān)控)配置和使用教程,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06微服務(wù)實戰(zhàn)之怎樣提升springboot服務(wù)吞吐量
這篇文章主要介紹了微服務(wù)實戰(zhàn)之怎樣提升springboot服務(wù)吞吐量方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08SpringBoot項目沒有把依賴的jar包一起打包的問題解決
這篇文章主要介紹了SpringBoot項目沒有把依賴的jar包一起打包的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-09-09Java并發(fā)編程中使用Executors類創(chuàng)建和管理線程的用法
這篇文章主要介紹了Java并發(fā)編程中使用Executors類創(chuàng)建和管理線程的用法,文中舉了用其啟動線程和設(shè)置線程優(yōu)先級的例子,需要的朋友可以參考下2016-03-03