中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

synchronized的特性有哪些

發布時間:2020-07-08 10:00:20 來源:億速云 閱讀:189 作者:Leah 欄目:編程語言

本篇文章為大家展示了synchronized的特性有哪些,代碼簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

1. synchronized鎖重入

1.1 介紹

關鍵字synchronized擁有鎖重入的功能,也就是在使用synchronized時,當一個線程得到一個對象鎖后,再次請求此對象鎖時是可以再次得到該對象的鎖的。這說明在一個synchronized方法/塊內部調用本類的其他synchronized方法/塊時,是永遠可以得到鎖的。

例如:

public class Service1 {

    public synchronized void method1(){
        System.out.println("method1");
        method2();
    }

    public synchronized void method2(){
        System.out.println("method2");
        method3();
    }

    public synchronized void method3(){
        System.out.println("method3");
    }

}
public class MyThread extends Thread {

    @Override
    public void run(){
        Service1 service1 = new Service1();
        service1.method1();
    }


    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

運行結果如下:
synchronized的特性有哪些
? 看到這個結果的時候是茫然了,怎么就證明是可重入鎖的了呢?
? “可重入鎖”的概念是:自己可以再次獲取自己的內部鎖,比如有1個線程獲得了某個對象的鎖,此時這個對象鎖還沒有釋放,當其再次想要獲取這個對象的鎖的時候還是可以獲取的,如果不可鎖重入的話,就會造成死鎖。
? “可重入鎖”的最大作用就是避免死鎖

1.2 分析

我們知道,在程序中,是無法顯式釋放對同步監視器的鎖的,而會在如下幾個情況下釋放鎖:
① 當前線程的同步方法、代碼塊執行結束的時候釋放
② 當前線程在同步方法、同步代碼塊遇到break、return終止該代碼塊或方法的時候釋放
③ 出現未處理的error或exception導致異常結束的時候釋放
④ 程序執行了同步對象wait方法,當前線程暫停,釋放鎖

那么,在上面的程序中,當線程進入同步方法method1時獲得Service1的對象鎖,但是在執行method1的時候調用了同步方法method2,按照正常情況,在執行同步方法method2同樣需要獲得對象鎖,但是根據上面釋放鎖的條件,此時method1的對象鎖還沒有釋放,此時就會造成死鎖,無法繼續執行method2。但是通過上面代碼的執行結果來看,能夠正常執行method2和method3,這就說明,在一個Synchronized修飾的方法或代碼塊的內部調用本類的其他Synchronized修飾的方法或代碼塊時,是永遠可以得到鎖的

1.3 父子可繼承性

可重入鎖支持在父子類繼承的環境中,示例代碼如下:

public class Service2 {
    public int i = 10;
    public synchronized void mainMethod(){
        i--;
        System.out.println("main print i="+i);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class Service3 extends Service2 {

    public synchronized void subMethod(){
        try{
            while (i>0){
                i--;
                System.out.println("sub print i= "+i);
                Thread.sleep(100);
                this.mainMethod();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
public class MyThread extends Thread {

    @Override
    public void run(){
        Service3 service3 = new Service3();
        service3.subMethod();
    }


    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

運行結果如下:
synchronized的特性有哪些
此程序說明,當存在父子類繼承關系時,子類完全可以通過“可重入鎖”調用父類的同步方法。

2. 出現異常,鎖自動釋放

當一個線程執行的代碼出現異常時,其所持有的鎖會自動釋放。
驗證代碼如下:

public class Service4 {

    public synchronized void testMethod(){
        if(Thread.currentThread().getName().equals("a")){
            System.out.println("ThreadName= "+Thread.currentThread().getName()+" run beginTime="+System.currentTimeMillis());
            int i=1;
            while (i == 1){
                if((""+Math.random()).substring(0,8).equals("0.123456")){
                    System.out.println("ThreadName= "+Thread.currentThread().getName()+" run exceptionTime="+System.currentTimeMillis());
                  //Integer.parseInt("a");
                }
            }
        }else{
            System.out.println("Thread B run time= "+System.currentTimeMillis());
        }
    }
}
public class ThreadA extends Thread{

    private Service4 service4;

    public ThreadA(Service4 service4){
        this.service4 = service4;
    }

    @Override
    public void run(){
        service4.testMethod();
    }
}
public class ThreadB extends Thread{

    private Service4 service4;

    public ThreadB(Service4 service4){
        this.service4 = service4;
    }

    @Override
    public void run(){
        service4.testMethod();
    }
}
public class Main {
    public static void main(String[] args) {
        try {
            Service4 service4 = new Service4();

            ThreadA a = new ThreadA(service4);
            a.setName("a");
            a.start();

            Thread.sleep(500);

            ThreadB b = new ThreadB(service4);
            b.setName("b");
            b.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

注意Service4類中Integer.parseInt(“a”);此時處于被注釋狀態,運行結果如下:
synchronized的特性有哪些
由于a線程沒有錯誤,while(true),此時a線程處于無限循環狀態,鎖一直被a占用,b線程無法獲得鎖,即無法執行b線程。

將Service4類中Integer.parseInt(“a”);解開注釋,執行的結果如下:

synchronized的特性有哪些
  
當a線程發生錯誤時,b線程獲得鎖從而執行,由此可見,當方法出現異常時,鎖自動釋放。

3. 將任意對象作為監視器

java支持對“任意對象”作為“對象監視器”來實現同步的功能。這個“任意對象”大多數是實例變量及方法的參數,使用格式為synchronized(非this對象x)同步代碼塊。
示例代碼如下:

public class StringLock {

    private String lock = "lock";

    public void method(){
        synchronized (lock){
            try {
                System.out.println("當前線程: "+Thread.currentThread().getName() + "開始");
                Thread.sleep(1000);
                System.out.println("當前線程: "+Thread.currentThread().getName() + "結束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        final StringLock stringLock = new StringLock();
        new Thread(new Runnable() {
            @Override
            public void run() {
                stringLock.method();
            }
        },"t1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                stringLock.method();
            }
        },"t2").start();
    }
}

運行結果如下:
synchronized的特性有哪些
鎖非this對象具有一定的優點:如果在一個類中有很多個synchronized方法,這時雖然能實現同步,但會受到阻塞,所以影響運行效率;但如果使用同步代碼塊鎖非this對象,則synchronized(非this)代碼塊中的程序與同步方法是異步的,不予其他鎖this同步方法爭搶this鎖,則可大大提高運行效率。

4. 同步不具有繼承性

父類的同步方法,在子類中重寫后不加同步關鍵字,是不會同步的,所以還得在子類的方法中添加synchronized關鍵字。

上述內容就是synchronized的特性有哪些,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

涞源县| 扎赉特旗| 文登市| 伊金霍洛旗| 上思县| 卫辉市| 五指山市| 卓尼县| 吉安县| 临猗县| 正安县| 嘉定区| 县级市| 黑龙江省| 屯昌县| 天峻县| 洛宁县| 龙陵县| 河西区| 闸北区| 万全县| 阿拉善右旗| 枣庄市| 鄱阳县| 汤原县| 德清县| 湘西| 张家界市| 内江市| 江西省| 法库县| 栾城县| 雷州市| 清河县| 岳普湖县| 紫金县| 孙吴县| 富顺县| 维西| 德清县| 岑溪市|