bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

synchronized傳統線程互斥技術怎么用

本文小編為大家詳細介紹“synchronized傳統線程互斥技術怎么用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“synchronized傳統線程互斥技術怎么用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

我們提供的服務有:成都做網站、網站制作、成都外貿網站建設、微信公眾號開發、網站優化、網站認證、薩嘎ssl等。為上千家企事業單位解決了網站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的薩嘎網站制作公司

在多個線程同時操作相同資源的時候,就會遇到并發的問題,如銀行轉賬啊、售票系統啊等。為了避免這些問題的出現,我們可以使用 synchronized 關鍵字來解決,下面針對 synchronized 常見的用法做一個總結。首先寫一個存在并發問題的程序,如下:

public class TraditionalThreadSynchronized {
    public static void main(String[] args) {
        //在靜態方法中不能new內部類的實例對象
        //private Outputer outputer = new Outputer();
        new TraditionalThreadSynchronized().init();
    }
    private void init() {
        final Outputer outputer = new Outputer();
        //線程1打印:duoxiancheng
        new Thread(new Runnable() {         
            @Override
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    outputer.output1("duoxiancheng");
                }
            }
        }).start();;
        //線程2打印:eson15
        new Thread(new Runnable() {         
            @Override
            public void run() {
                while(true) {
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    outputer.output1("eson15");
                }
            }
        }).start();;
    }
    static class Outputer {
        //自定義一個字符串打印方法,一個個字符的打印
        public void output1(String name) {
            int len = name.length();
            for(int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println("");     
        }       
    }
}

在內部類 Outputer 中定義了一個打印字符串的方法,一個字符一個字符的打印,這樣比較容易直觀的看出并發問題,因為字符順序打亂了就說明出現問題了。然后在 init 方法中開啟兩個線程,一個線程打印 “duoxiancheng” ,另一個線程打印 “eson15”。看一下運行結果:

eson15duoxianche
ng
eson15
duoxiancheng
duoxiancheng
eson15
esduoxiancheng
on15
duoxiancheng

從輸出的結果中可以看到,已經出現問題了,為了解決這個問題,可以使用 synchronized 同步代碼塊來對公共部分進行同步操作,但是需要給它一把鎖,這把鎖是一個對象,可以是任意一個對象,但是前提是,兩個線程使用的必須是同一個對象鎖才可以,這很好理解。那么下面在 output1() 方法中加入 synchronized 代碼塊:

static class Outputer {
    private String token = ""; //定義一個鎖
    public void output1(String name) {
        synchronized(token) //任何一個對象都可以作為參數,但是該對象對于兩個線程來說是同一個才行
        //如果用name就不行了,因為不同的線程進來name是不一樣的,不是同一個name
        {
            int len = name.length();
            for(int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println("");     
        }
    }
}

經過上面的改造,線程安全問題就基本解決了,但是還可以再往下引申,如果在方法上加 synchronized 關鍵字的話,那么這個同步鎖是什么呢?我們在 Outputer 類中再寫一個 output2() 方法:

static class Outputer {
    private String token = ""; //定義一個鎖
    public void output1(String name) {
        synchronized(token) //任何一個對象都可以作為參數,但是該對象對于兩個線程來說是同一個才行
        {
            int len = name.length();
            for(int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println("");     
        }
    }   
    public synchronized void output2(String name) {
        int len = name.length();
        for(int i = 0; i < len; i++) {
            System.out.print(name.charAt(i));
        }
        System.out.println("");     
    }   
}

方法內部實現邏輯一模一樣,唯一不同的就是 synchronized 加在了方法上,那么我們讓 init() 方法中的兩個線程中,一個調用 output1(Stringname) 方法,另一個調用 output2(Stringname) 方法,從結果中能看出,線程安全問題又出現了。產生問題的原因不難發現:現在兩個方法都加了 synchronized,但是兩個線程在調用兩個不同的方法還是出現了問題,也就是說,還是各玩各的……那么問題就出在這個鎖上,說明兩者并沒有使用同一把鎖!
如果我們把 output1() 方法中 synchronized 中的 token 改成 this,再運行就沒問題了,這說明一點:synchronized 關鍵字修飾方法的時候,同步鎖是 this,即等效于代碼塊 synchronized(this){...}
再繼續往下引申,現在在 Outputer 類中再寫一個靜態方法 output3(Stringname),并且也讓 synchronized 去修飾這個靜態方法。

static class Outputer {
    private String token = ""; //定義一個鎖
    public void output1(String name) {
        synchronized(token) //任何一個對象都可以作為參數,但是該對象對于兩個線程來說是同一個才行
        {
            int len = name.length();
            for(int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println("");     
        }
    }   
    public static synchronized void output3(String name) {
        int len = name.length();
        for(int i = 0; i < len; i++) {
            System.out.print(name.charAt(i));
        }
        System.out.println("");     
        }   
    }
}

然后在 init() 方法中一個線程調用 output1() 方法,另一個線程調用 output3() 方法。毫無疑問,肯定又會出現線程安全問題。但是如何解決呢?因為 static 方法在類加載的時候就加載了,所以這個鎖應該是類的字節碼對象。那么將 token 改為 Outputer.class 就解決問題了,這說明一點:synchronized 關鍵字修飾 static 方法的時候,同步鎖是該類的字節碼對象,即等效于代碼塊 synchronized(classname.class){...}
最后再總結一下:

  • 同步代碼塊的鎖是任意對象。只要不同的線程都執行同一個同步代碼塊的時候,這個鎖隨便設。

  • 同步函數的鎖是固定的 this。當需要和同步函數中的邏輯實行同步的時候,代碼塊中的鎖必須為 this。

  • 靜態同步函數的鎖是該函數所屬類的字節碼文件對象。該對象可以用 this.getClass() 方法獲取,也可以使用 當前類名.class 表示。

讀到這里,這篇“synchronized傳統線程互斥技術怎么用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注創新互聯行業資訊頻道。

網頁名稱:synchronized傳統線程互斥技術怎么用
鏈接分享:http://vcdvsql.cn/article48/pcoeep.html

成都網站建設公司_創新互聯,為您提供商城網站營銷型網站建設自適應網站全網營銷推廣建站公司企業建站

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站優化排名