亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

java多線程:synchronized

entner / 3442人閱讀

摘要:非靜態(tài)方法以及方法內(nèi)部的代碼塊持有的是同一個(gè)對象鎖,它們是同步執(zhí)行的??芍厝腈i使用時(shí),當(dāng)一個(gè)線程請求一個(gè)對象鎖時(shí),再次請求該鎖是可以立即得到的。出現(xiàn)異常,會自動釋放鎖同步方法與同步代碼塊作用于整個(gè)方法,可能引起方法執(zhí)行效率下降。

synchronize可以在多個(gè)線程操作同一個(gè)成員變量或者方法時(shí),實(shí)現(xiàn)同步(或者互斥)的效果。
synchronized可以作用于方法,以及方法內(nèi)部的代碼塊。

//1 
synchronized void method(){}
   //2
static synchronized void method(){}
//3
synchronized void method(){
    synchronized(鎖對象){
    }
}
//4
static synchronized void method(){
    synchronized(鎖對象){
    }
}
鎖對象

那么在上面的示例中,它們分別持有的鎖對象是誰?
synchronized作用于非靜態(tài)方法以及非靜態(tài)方法內(nèi)部的代碼塊,持有的是當(dāng)前類的對象的鎖,并且是同一個(gè)鎖。作用于靜態(tài)方法及其內(nèi)部的代碼塊,持有的是當(dāng)前類的Class對象的鎖,并且和非靜態(tài)方法不是同一個(gè)鎖。
通過代碼來驗(yàn)證。

public class SynchronizedTest {

    private synchronized void test1(){
        for (int x = 0; x < 5; x++) {

            System.out.println("test1---"+x);
        }
    }
    private  void test2(){
        synchronized(this) {
            for (int x = 0; x < 5; x++) {

                System.out.println("---test2---"+x);
            }
        }
    }

    private static synchronized void test3(){
        for (int x = 0; x < 5; x++) {

            System.out.println("------test3---"+x);
        }
    }

    private static  void test4(){
        synchronized (SynchronizedTest.class){
            for (int x = 0; x < 5; x++) {

                System.out.println("---------test4---"+x);
            }
        }
    }

    public static void main(String[] args) {
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronizedTest.test1();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronizedTest.test2();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test3();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test4();
            }
        }).start();
    }
}

執(zhí)行結(jié)果

test1---0
------test3---0
test1---1
------test3---1
test1---2
test1---3
------test3---2
test1---4
------test3---3
------test3---4
---test2---0
---test2---1
---test2---2
---test2---3
---test2---4
---------test4---0
---------test4---1
---------test4---2
---------test4---3
---------test4---4

test1和test2不會交叉執(zhí)行,test3和test4也不會交叉執(zhí)行。非靜態(tài)方法以及方法內(nèi)部的代碼塊持有的是同一個(gè)對象鎖,它們是同步執(zhí)行的。靜態(tài)方法和內(nèi)部的代碼塊持有的是當(dāng)前類的Class對象鎖,它們是同步執(zhí)行的。而靜態(tài)方法和非靜態(tài)方法持有的不是同一個(gè)鎖,它們是異步的。

String作為鎖

字符串常量作為鎖,會有什么結(jié)果?

        final String a = "100";
        final String b = "100";
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (a){
                    while (true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName());
                    }
                }
            }
        },"thread-a").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (b){
                    while (true){
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName());
                    }
                }
            }
        },"thread-b").start();

這里字符串a(chǎn)和b雖然是兩個(gè)對象,但是聲明b時(shí),會將字符串常量池中已存在的a的值直接賦給b。這樣a和b其實(shí)是一樣的。這樣線程thread-a和thread-b同時(shí)搶占同一個(gè)鎖,一旦一個(gè)線程搶到該鎖,另一個(gè)線程就再也獲取不到該鎖。

synchronized不具有繼承性

自己覆蓋了父類被synchronized修飾的方法,子類方法如果需要同步性,也需要用synchronized修飾。
定義子類Sub繼承自SynchronizedTest

class Sub extends SynchronizedTest{
    @Override
    public void test2() {
        //super.test2();
        for (int x = 0; x < 15; x++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
}

然后開啟兩個(gè)線程調(diào)用Sub的test2()方法。

final  Sub sub = new Sub();
       new Thread(new Runnable() {
           @Override
           public void run() {
               sub.test2();
           }
       },"Sub---A").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                sub.test2();
            }
        },"Sub---B").start();

打印結(jié)果

Sub---A
Sub---B
Sub---A
Sub---B
Sub---A
Sub---B
Sub---A
Sub---B

可見Sub的test2()方法并沒有同步性。也就是synchronized不能被繼承。

可重入鎖

使用synchronized時(shí),當(dāng)一個(gè)線程請求一個(gè)對象鎖時(shí),再次請求該鎖是可以立即得到的。

public class SynchronizedTest {

    private synchronized void test1(){
        for (int x = 0; x < 5; x++) {

            System.out.println("test1---"+x);
        }
        test2();
    }
    public  void test2(){
        synchronized(this) {
            for (int x = 0; x < 5; x++) {

                System.out.println("---test2---"+x);
            }
        }
    }
    
    public static void main(String[] args) {
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronizedTest.test1();
            }
        }).start();
        
    }
 }

在方法test1()中調(diào)用方法test2(),并不需要等待鎖,而是立即獲取到鎖。
把子類Sub的test2()方法也改成synchronized修飾。并在其內(nèi)部調(diào)用父類的test2()方法。能獲得鎖嗎?

class Sub extends SynchronizedTest{
    @Override
    public synchronized void test2() {
        //調(diào)用父類的同步方法
        super.test2();
        for (int x = 0; x < 15; x++) {
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }
}

打印結(jié)果

---test2---0
---test2---1
---test2---2
---test2---3
---test2---4
Sub---A
Sub---A
Sub---A
Sub---A

可以看到父類方法執(zhí)行完畢,子類的方法立即執(zhí)行。可見,在子父類的繼承關(guān)系中,也支持可重入鎖這個(gè)特性。

出現(xiàn)異常,會自動釋放鎖 同步方法與同步代碼塊

synchronized作用于整個(gè)方法,可能引起方法執(zhí)行效率下降。建議將方法內(nèi)部需要同步的代碼用synchronized修飾,也就是synchronized代碼塊。

多個(gè)同步鎖對象

在一個(gè)類中假如有多個(gè)同步方法,它們之間并不需要互斥。那么使用同一個(gè)鎖,會大大降低效率??梢远x多個(gè)同步鎖對象。

 Object obj1 = new Object();
 Object obj2 = new Object();
    
 public void method1(){
  synchronized(obj1){

}
}

 public void method2(){
  synchronized(obj2){

}
}

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/77669.html

相關(guān)文章

  • Java線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1)

    摘要:轉(zhuǎn)載請備注地址多線程學(xué)習(xí)二將分為兩篇文章介紹同步方法另一篇介紹同步語句塊。如果兩個(gè)線程同時(shí)操作對象中的實(shí)例變量,則會出現(xiàn)非線程安全,解決辦法就是在方法前加上關(guān)鍵字即可。 轉(zhuǎn)載請備注地址: https://blog.csdn.net/qq_3433... Java多線程學(xué)習(xí)(二)將分為兩篇文章介紹synchronized同步方法另一篇介紹synchronized同步語句塊。系列文章傳送門...

    xuxueli 評論0 收藏0
  • Java線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2)

    摘要:關(guān)鍵字加到非靜態(tài)方法上持有的是對象鎖。線程和線程持有的鎖不一樣,所以和運(yùn)行同步,但是和運(yùn)行不同步。所以盡量不要使用而使用參考多線程編程核心技術(shù)并發(fā)編程的藝術(shù)如果你覺得博主的文章不錯(cuò),歡迎轉(zhuǎn)發(fā)點(diǎn)贊。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(2) J...

    Batkid 評論0 收藏0
  • Java 線程核心技術(shù)梳理(附源碼)

    摘要:本文對多線程基礎(chǔ)知識進(jìn)行梳理,主要包括多線程的基本使用,對象及變量的并發(fā)訪問,線程間通信,的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。源碼采用構(gòu)建,多線程這部分源碼位于模塊中。通知可能等待該對象的對象鎖的其他線程。 本文對多線程基礎(chǔ)知識進(jìn)行梳理,主要包括多線程的基本使用,對象及變量的并發(fā)訪問,線程間通信,lock的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。 寫在前面 花了一周時(shí)...

    Winer 評論0 收藏0
  • Java線程基礎(chǔ)(一)——線程與鎖

    摘要:一線程的基本概念單線程簡單的說,單線程就是進(jìn)程中只有一個(gè)線程。多線程由一個(gè)以上線程組成的程序稱為多線程程序。當(dāng)線程調(diào)用完方法進(jìn)入后會自動釋放鎖,線程獲得鎖。 一、線程的基本概念 1.1 單線程 簡單的說,單線程就是進(jìn)程中只有一個(gè)線程。單線程在程序執(zhí)行時(shí),所走的程序路徑按照連續(xù)順序排下來,前面的必須處理好,后面的才會執(zhí)行。 Java示例: public class SingleThrea...

    WelliJhon 評論0 收藏0
  • Java鎖機(jī)制了解一下

    摘要:底層是是通過對象,對象有自己的對象頭,存儲了很多信息,其中一個(gè)信息標(biāo)示是被哪個(gè)線程持有。當(dāng)一個(gè)線程執(zhí)行的代碼出現(xiàn)異常時(shí),其所持有的鎖會自動釋放。 前言 回顧前面: 多線程三分鐘就可以入個(gè)門了! Thread源碼剖析 多線程基礎(chǔ)必要知識點(diǎn)!看了學(xué)習(xí)多線程事半功倍 只有光頭才能變強(qiáng)! 本文章主要講的是Java多線程加鎖機(jī)制,有兩種: Synchronized 顯式Lock 不得不嘮...

    hyuan 評論0 收藏0
  • JAVA線程機(jī)制解析-volatile&synchronized

    摘要:當(dāng)一個(gè)線程持有重量級鎖時(shí),另外一個(gè)線程就會被直接踢到同步隊(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 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<