成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Java鎖機(jī)制了解一下

hyuan / 534人閱讀

摘要:底層是是通過對(duì)象,對(duì)象有自己的對(duì)象頭,存儲(chǔ)了很多信息,其中一個(gè)信息標(biāo)示是被哪個(gè)線程持有。當(dāng)一個(gè)線程執(zhí)行的代碼出現(xiàn)異常時(shí),其所持有的鎖會(huì)自動(dòng)釋放。

前言

回顧前面:

多線程三分鐘就可以入個(gè)門了!

Thread源碼剖析

多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍

只有光頭才能變強(qiáng)!

本文章主要講的是Java多線程加鎖機(jī)制,有兩種:

Synchronized

顯式Lock

不得不嘮叨幾句:

在《Java核心技術(shù)卷 一》是先講比較難的顯式Lock,而再講的是比較簡(jiǎn)單的Synchronized

而《Java并發(fā)編程實(shí)戰(zhàn)》在前4章零散地講解了Synchronized,將顯式Lock放到了13章

其實(shí)都比較坑,如果能先系統(tǒng)講了Synchronized鎖機(jī)制,接著講顯式Lock鎖機(jī)制,那就很容易理解了。也不需要跨那么多章節(jié)。

那么接下來我們就開始吧~

一、synchronized鎖 1.1synchronized鎖是什么?

synchronized是Java的一個(gè)關(guān)鍵字,它能夠?qū)?strong>代碼塊(方法)鎖起來

它使用起來是非常簡(jiǎn)單的,只要在代碼塊(方法)添加關(guān)鍵字synchronized,即可以實(shí)現(xiàn)同步的功能~

    public synchronized void test() {
        // 關(guān)注公眾號(hào)Java3y
        // doSomething
    }

synchronized是一種互斥鎖

一次只能允許一個(gè)線程進(jìn)入被鎖住的代碼塊

synchronized是一種內(nèi)置鎖/監(jiān)視器鎖

Java中每個(gè)對(duì)象都有一個(gè)內(nèi)置鎖(監(jiān)視器,也可以理解成鎖標(biāo)記),而synchronized就是使用對(duì)象的內(nèi)置鎖(監(jiān)視器)來將代碼塊(方法)鎖定的!

1.2synchronized用處是什么?

synchronized保證了線程的原子性。(被保護(hù)的代碼塊是一次被執(zhí)行的,沒有任何線程會(huì)同時(shí)訪問)

synchronized還保證了可見性。(當(dāng)執(zhí)行完synchronized之后,修改后的變量對(duì)其他的線程是可見的)

Java中的synchronized,通過使用內(nèi)置鎖,來實(shí)現(xiàn)對(duì)變量的同步操作,進(jìn)而實(shí)現(xiàn)了對(duì)變量操作的原子性和其他線程對(duì)變量的可見性,從而確保了并發(fā)情況下的線程安全。

1.3synchronized的原理

我們首先來看一段synchronized修飾方法和代碼塊的代碼:

public class Main {
    //修飾方法
    public synchronized void test1(){

    }

    
    public void test2(){
        // 修飾代碼塊
        synchronized (this){

        }
    }
}

來反編譯看一下:

同步代碼塊

monitorenter和monitorexit指令實(shí)現(xiàn)的

同步方法(在這看不出來需要看JVM底層實(shí)現(xiàn))

方法修飾符上的ACC_SYNCHRONIZED實(shí)現(xiàn)。

synchronized底層是是通過monitor對(duì)象,對(duì)象有自己的對(duì)象頭,存儲(chǔ)了很多信息,其中一個(gè)信息標(biāo)示是被哪個(gè)線程持有。

具體可參考:

https://blog.csdn.net/chenssy/article/details/54883355

https://blog.csdn.net/u012465296/article/details/53022317

1.4synchronized如何使用

synchronized一般我們用來修飾三種東西:

修飾普通方法

修飾代碼塊

修飾靜態(tài)方法

1.4.1修飾普通方法:

用的鎖是Java3y對(duì)象(內(nèi)置鎖)

public class Java3y {


    // 修飾普通方法,此時(shí)用的鎖是Java3y對(duì)象(內(nèi)置鎖)
    public synchronized void test() {
        // 關(guān)注公眾號(hào)Java3y
        // doSomething
    }

}
1.4.2修飾代碼塊:

用的鎖是Java3y對(duì)象(內(nèi)置鎖)--->this

public class Java3y {
    
    public  void test() {
        
        // 修飾代碼塊,此時(shí)用的鎖是Java3y對(duì)象(內(nèi)置鎖)--->this
        synchronized (this){
            // 關(guān)注公眾號(hào)Java3y
            // doSomething
        }
    }
}

當(dāng)然了,我們使用synchronized修飾代碼塊時(shí)未必使用this,還可以使用其他的對(duì)象(隨便一個(gè)對(duì)象都有一個(gè)內(nèi)置鎖)

所以,我們可以這樣干:

public class Java3y {


    // 使用object作為鎖(任何對(duì)象都有對(duì)應(yīng)的鎖標(biāo)記,object也不例外)
    private Object object = new Object();


    public void test() {

        // 修飾代碼塊,此時(shí)用的鎖是自己創(chuàng)建的鎖Object
        synchronized (object){
            // 關(guān)注公眾號(hào)Java3y
            // doSomething
        }
    }

}

上面那種方式(隨便使用一個(gè)對(duì)象作為鎖)在書上稱之為-->客戶端鎖,這是不建議使用的。

書上想要實(shí)現(xiàn)的功能是:給ArrayList添加一個(gè)putIfAbsent(),這需要是線程安全的。

假定直接添加synchronized是不可行的

使用客戶端鎖,會(huì)將當(dāng)前的實(shí)現(xiàn)與原本的list耦合了

書上給出的辦法是使用組合的方式(也就是裝飾器模式)

1.4.3修飾靜態(tài)方法

獲取到的是類鎖(類的字節(jié)碼文件對(duì)象):Java3y.class

public class Java3y {

    // 修飾靜態(tài)方法代碼塊,靜態(tài)方法屬于類方法,它屬于這個(gè)類,獲取到的鎖是屬于類的鎖(類的字節(jié)碼文件對(duì)象)-->Java3y.class
    public synchronized void test() {

        // 關(guān)注公眾號(hào)Java3y
        // doSomething
    }
}
1.4.4類鎖與對(duì)象鎖

synchronized修飾靜態(tài)方法獲取的是類鎖(類的字節(jié)碼文件對(duì)象),synchronized修飾普通方法或代碼塊獲取的是對(duì)象鎖。

它倆是不沖突的,也就是說:獲取了類鎖的線程和獲取了對(duì)象鎖的線程是不沖突的!

public class SynchoronizedDemo {

    //synchronized修飾非靜態(tài)方法
    public synchronized void function() throws InterruptedException {
        for (int i = 0; i <3; i++) {
            Thread.sleep(1000);
            System.out.println("function running...");
        }
    }
    //synchronized修飾靜態(tài)方法
    public static synchronized void staticFunction()
            throws InterruptedException {
        for (int i = 0; i < 3; i++) {
            Thread.sleep(1000);
            System.out.println("Static function running...");
        }
    }

    public static void main(String[] args) {
        final SynchoronizedDemo demo = new SynchoronizedDemo();

        // 創(chuàng)建線程執(zhí)行靜態(tài)方法
        Thread t1 = new Thread(() -> {
            try {
                staticFunction();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 創(chuàng)建線程執(zhí)行實(shí)例方法
        Thread t2 = new Thread(() -> {
            try {
                demo.function();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        // 啟動(dòng)
        t1.start();
        t2.start();
    }
}

結(jié)果證明:類鎖和對(duì)象鎖是不會(huì)沖突的!

1.5重入鎖

我們來看下面的代碼:

public class Widget {

    // 鎖住了
    public synchronized void doSomething() {
        ...
    }
}

public class LoggingWidget extends Widget {

    // 鎖住了
    public synchronized void doSomething() {
        System.out.println(toString() + ": calling doSomething");
        super.doSomething();
    }
}

當(dāng)線程A進(jìn)入到LoggingWidget的doSomething()方法時(shí),此時(shí)拿到了LoggingWidget實(shí)例對(duì)象的鎖。

隨后在方法上又調(diào)用了父類Widget的doSomething()方法,它又是被synchronized修飾。

那現(xiàn)在我們LoggingWidget實(shí)例對(duì)象的鎖還沒有釋放,進(jìn)入父類Widget的doSomething()方法還需要一把鎖嗎?

不需要的!

因?yàn)?strong>鎖的持有者是“線程”,而不是“調(diào)用”。線程A已經(jīng)是有了LoggingWidget實(shí)例對(duì)象的鎖了,當(dāng)再需要的時(shí)候可以繼續(xù)“開鎖”進(jìn)去的!

這就是內(nèi)置鎖的可重入性。

1.6釋放鎖的時(shí)機(jī)

當(dāng)方法(代碼塊)執(zhí)行完畢后會(huì)自動(dòng)釋放鎖,不需要做任何的操作。

當(dāng)一個(gè)線程執(zhí)行的代碼出現(xiàn)異常時(shí),其所持有的鎖會(huì)自動(dòng)釋放

不會(huì)由于異常導(dǎo)致出現(xiàn)死鎖現(xiàn)象~

二、Lock顯式鎖 2.1Lock顯式鎖簡(jiǎn)單介紹

Lock顯式鎖是JDK1.5之后才有的,之前我們都是使用Synchronized鎖來使線程安全的~

Lock顯式鎖是一個(gè)接口,我們來看看:

隨便翻譯一下他的頂部注釋,看看是干嘛用的:

可以簡(jiǎn)單概括一下:

Lock方式來獲取鎖支持中斷、超時(shí)不獲取、是非阻塞的

提高了語(yǔ)義化,哪里加鎖,哪里解鎖都得寫出來

Lock顯式鎖可以給我們帶來很好的靈活性,但同時(shí)我們必須手動(dòng)釋放鎖

支持Condition條件對(duì)象

允許多個(gè)讀線程同時(shí)訪問共享資源

2.2synchronized鎖和Lock鎖使用哪個(gè)

前面說了,Lock顯式鎖給我們的程序帶來了很多的靈活性,很多特性都是Synchronized鎖沒有的。那Synchronized鎖有沒有存在的必要??

必須是有的??!Lock鎖在剛出來的時(shí)候很多性能方面都比Synchronized鎖要好,但是從JDK1.6開始Synchronized鎖就做了各種的優(yōu)化(畢竟親兒子,牛逼)

優(yōu)化操作:適應(yīng)自旋鎖,鎖消除,鎖粗化,輕量級(jí)鎖,偏向鎖。

詳情可參考:https://blog.csdn.net/chenssy/article/details/54883355

所以,到現(xiàn)在Lock鎖和Synchronized鎖的性能其實(shí)差別不是很大!而Synchronized鎖用起來又特別簡(jiǎn)單。Lock鎖還得顧忌到它的特性,要手動(dòng)釋放鎖才行(如果忘了釋放,這就是一個(gè)隱患)

所以說,我們絕大部分時(shí)候還是會(huì)使用Synchronized鎖,用到了Lock鎖提及的特性,帶來的靈活性才會(huì)考慮使用Lock顯式鎖~

2.3公平鎖

公平鎖理解起來非常簡(jiǎn)單:

線程將按照它們發(fā)出請(qǐng)求的順序來獲取鎖

非公平鎖就是:

線程發(fā)出請(qǐng)求的時(shí)可以“插隊(duì)”獲取鎖

Lock和synchronize都是默認(rèn)使用非公平鎖的。如果不是必要的情況下,不要使用公平鎖

公平鎖會(huì)來帶一些性能的消耗的

四、最后

本文講了synchronized內(nèi)置鎖和簡(jiǎn)單描述了一下Lock顯式鎖,總得來說:

synchronized好用,簡(jiǎn)單,性能不差

沒有使用到Lock顯式鎖的特性就不要使用Lock鎖了。

Lock鎖這里只是介紹了一些些,明天會(huì)詳解它的相關(guān)子類和需要注意的地方,敬請(qǐng)期待~

之前在學(xué)習(xí)操作系統(tǒng)的時(shí)候根據(jù)《計(jì)算機(jī)操作系統(tǒng)-湯小丹》這本書也做了一點(diǎn)點(diǎn)筆記,都是比較淺顯的知識(shí)點(diǎn)?;蛟S對(duì)大家有幫助

操作系統(tǒng)第一篇【引論】

操作系統(tǒng)第二篇【進(jìn)程管理】

操作系統(tǒng)第三篇【線程】

操作系統(tǒng)第四篇【處理機(jī)調(diào)度】

操作系統(tǒng)第五篇【死鎖】

操作系統(tǒng)第六篇【存儲(chǔ)器管理】

操作系統(tǒng)第七篇【設(shè)備管理】

參考資料:

《Java核心技術(shù)卷一》

《Java并發(fā)編程實(shí)戰(zhàn)》

《計(jì)算機(jī)操作系統(tǒng)-湯小丹》

https://blog.csdn.net/panweiwei1994/article/details/78483167

http://www.cnblogs.com/dolphin0520/category/602384.html

https://blog.csdn.net/chenssy/article/category/3145247

https://blog.csdn.net/u012465296/article/details/53022317

https://www.cnblogs.com/wxd0108/p/5479442.html

如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y。為了大家方便,剛新建了一下qq群:742919422,大家也可以去交流交流。謝謝支持了!希望能多介紹給其他有需要的朋友

文章的目錄導(dǎo)航

https://zhongfucheng.bitcron.com/post/shou-ji/wen-zhang-dao-hang

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/71175.html

相關(guān)文章

  • Java面試 32個(gè)核心必考點(diǎn)完全解析

    摘要:如問到是否使用某框架,實(shí)際是是問該框架的使用場(chǎng)景,有什么特點(diǎn),和同類可框架對(duì)比一系列的問題。這兩個(gè)方向的區(qū)分點(diǎn)在于工作方向的側(cè)重點(diǎn)不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個(gè)核心必考點(diǎn)完全解析(完) 課程預(yù)習(xí) 1.1 課程內(nèi)容分為三個(gè)模塊 基礎(chǔ)模塊: 技術(shù)崗位與面試 計(jì)算機(jī)基礎(chǔ) JVM原理 多線程 設(shè)計(jì)模式 數(shù)據(jù)結(jié)構(gòu)與算法 應(yīng)用模塊: 常用工具集 ...

    JiaXinYi 評(píng)論0 收藏0
  • JAVA多線程機(jī)制解析-volatile&synchronized

    摘要:當(dāng)一個(gè)線程持有重量級(jí)鎖時(shí),另外一個(gè)線程就會(huì)被直接踢到同步隊(duì)列中等待。 java代碼先編譯成字節(jié)碼,字節(jié)碼最后編譯成cpu指令,因此Java的多線程實(shí)現(xiàn)最終依賴于jvm和cpu的實(shí)現(xiàn) synchronized和volatile 我們先來討論一下volatile關(guān)鍵字的作用以及實(shí)現(xiàn)機(jī)制,每個(gè)線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內(nèi)存模型了,我們...

    dendoink 評(píng)論0 收藏0
  • Java開發(fā) 大廠面試整理

    摘要:用戶態(tài)不能干擾內(nèi)核態(tài)所以指令就有兩種特權(quán)指令和非特權(quán)指令不同的狀態(tài)對(duì)應(yīng)不同的指令。非特權(quán)指令所有程序均可直接使用。用戶態(tài)常態(tài)目態(tài)執(zhí)行非特權(quán)指令。 這是我今年從三月份開始,主要的大廠面試經(jīng)過,有些企業(yè)面試的還沒來得及整理,可能有些沒有帶答案就發(fā)出來了,還請(qǐng)各位先思考如果是你怎么回答面試官?這篇文章會(huì)持續(xù)更新,請(qǐng)各位持續(xù)關(guān)注,希望對(duì)你有所幫助! 面試清單 平安產(chǎn)險(xiǎn) 飛豬 上汽大通 浩鯨科...

    Scorpion 評(píng)論0 收藏0
  • 你和阿里資深架構(gòu)師之間,差的不僅僅是年齡(進(jìn)階必看)

    摘要:導(dǎo)讀閱讀本文需要有足夠的時(shí)間,筆者會(huì)由淺到深帶你一步一步了解一個(gè)資深架構(gòu)師所要掌握的各類知識(shí)點(diǎn),你也可以按照文章中所列的知識(shí)體系對(duì)比自身,對(duì)自己進(jìn)行查漏補(bǔ)缺,覺得本文對(duì)你有幫助的話,可以點(diǎn)贊關(guān)注一下。目錄一基礎(chǔ)篇二進(jìn)階篇三高級(jí)篇四架構(gòu)篇五擴(kuò) 導(dǎo)讀:閱讀本文需要有足夠的時(shí)間,筆者會(huì)由淺到深帶你一步一步了解一個(gè)資深架構(gòu)師所要掌握的各類知識(shí)點(diǎn),你也可以按照文章中所列的知識(shí)體系對(duì)比自身,對(duì)自己...

    huaixiaoz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<