成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

java多線程:synchronized

entner / 3382人閱讀

摘要:非靜態(tài)方法以及方法內(nèi)部的代碼塊持有的是同一個(gè)對(duì)象鎖,它們是同步執(zhí)行的??芍厝腈i使用時(shí),當(dāng)一個(gè)線程請(qǐng)求一個(gè)對(duì)象鎖時(shí),再次請(qǐng)求該鎖是可以立即得到的。出現(xiàn)異常,會(huì)自動(dòng)釋放鎖同步方法與同步代碼塊作用于整個(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(鎖對(duì)象){
    }
}
//4
static synchronized void method(){
    synchronized(鎖對(duì)象){
    }
}
鎖對(duì)象

那么在上面的示例中,它們分別持有的鎖對(duì)象是誰(shuí)?
synchronized作用于非靜態(tài)方法以及非靜態(tài)方法內(nèi)部的代碼塊,持有的是當(dāng)前類(lèi)的對(duì)象的鎖,并且是同一個(gè)鎖。作用于靜態(tài)方法及其內(nèi)部的代碼塊,持有的是當(dāng)前類(lèi)的Class對(duì)象的鎖,并且和非靜態(tài)方法不是同一個(gè)鎖。
通過(guò)代碼來(lái)驗(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不會(huì)交叉執(zhí)行,test3和test4也不會(huì)交叉執(zhí)行。非靜態(tài)方法以及方法內(nèi)部的代碼塊持有的是同一個(gè)對(duì)象鎖,它們是同步執(zhí)行的。靜態(tài)方法和內(nèi)部的代碼塊持有的是當(dāng)前類(lèi)的Class對(duì)象鎖,它們是同步執(zhí)行的。而靜態(tài)方法和非靜態(tài)方法持有的不是同一個(gè)鎖,它們是異步的。

String作為鎖

字符串常量作為鎖,會(huì)有什么結(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è)對(duì)象,但是聲明b時(shí),會(huì)將字符串常量池中已存在的a的值直接賦給b。這樣a和b其實(shí)是一樣的。這樣線程thread-a和thread-b同時(shí)搶占同一個(gè)鎖,一旦一個(gè)線程搶到該鎖,另一個(gè)線程就再也獲取不到該鎖。

synchronized不具有繼承性

自己覆蓋了父類(lèi)被synchronized修飾的方法,子類(lèi)方法如果需要同步性,也需要用synchronized修飾。
定義子類(lèi)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());
        }
    }
}

然后開(kāi)啟兩個(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

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

可重入鎖

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

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

class Sub extends SynchronizedTest{
    @Override
    public synchronized void test2() {
        //調(diào)用父類(lèi)的同步方法
        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

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

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

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

多個(gè)同步鎖對(duì)象

在一個(gè)類(lèi)中假如有多個(gè)同步方法,它們之間并不需要互斥。那么使用同一個(gè)鎖,會(huì)大大降低效率。可以定義多個(gè)同步鎖對(duì)象。

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

}
}

 public void method2(){
  synchronized(obj2){

}
}

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77669.html

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

    hyuan 評(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 我們先來(lái)討論一下volatile關(guān)鍵字的作用以及實(shí)現(xiàn)機(jī)制,每個(gè)線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內(nèi)存模型了,我們...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<