java中synchronized幾種使用方法

在使用synchronized方法時,我總結(jié)了使用的情形:
第一種情形:

/**
 * Created by zhangzheming on 2018/1/12.
 */

public class SyncDubbo1 {

    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 static void main(String[] args){
        final SyncDubbo1 sd = new SyncDubbo1();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                sd.method1();
            }
        });
        t1.start();
    }
}
運(yùn)行結(jié)果

從上面的運(yùn)行結(jié)果可以看出:在嵌套方法中使用synchronized,多線程情況下是線程安全的。

第二種情況:

/**
 * Created by zhangzheming on 2018/1/12.
 */

public class syncDubbo2 {

    // 主類
    static class Main{
        public int i = 10;
        public synchronized void operationSup(){
            try {
                i--;
                System.out.println("Main print i= "+i);
                Thread.sleep(100);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    // 子類
    static class Sub extends Main{
        public synchronized void operationSub(){
            try{
                while (i>0){
                    i--;
                    System.out.println("Sub print i= "+i);
                    Thread.sleep(100);
                    this.operationSup();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args){
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                Sub sub = new Sub();
                sub.operationSub();
            }
        });

        t1.start();
    }
}
運(yùn)行結(jié)果

此種情形主要是說明兩點(diǎn):
(1)在出現(xiàn)父子類繼承關(guān)系的情況下,父類的成員變量也可以被子類繼承。
(2)在父類和子類都使用synchronized ,出現(xiàn)多線程情況下,是線程安全的。

synchronized 的使用出現(xiàn)異常情況下,如果遇到異常,我們也需要處理異常情況,請看下面的代碼:

/**
 * Created by zhangzheming on 2018/1/12.
 */

public class SyncException {

    private int i = 0;

    public synchronized void operation(){
        while (true){
            try{
                i++;
                Thread.sleep(200);
                System.out.println(Thread.currentThread().getName()+", i=" + i);
                if (i%10 == 0){
                    Integer.parseInt("a");
                }
            }catch (InterruptedException e){
                e.printStackTrace();
                // (3) contiune;
                 //(2)System.out.println("log info i = "+i);
                //(1)throw new RuntimeException();
            }
        }
    }

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

這段代碼其實(shí)將輸出變量i的累加值,但是每逢遇到被10整除的數(shù)時,就會遇到異?,F(xiàn)象,這種情況下,我們有三種解決辦法:
(1)第一種辦法:throw new RuntimeException(); 將運(yùn)行異常拋出,這樣程序就會停止下來,不會影響到后面的任務(wù),比較適合任務(wù)之前有先后順序的關(guān)聯(lián)關(guān)系;
(2)第二種辦法:System.out.println("log info i = "+i);將錯誤信息打印出來或者打印到日志中出,事后進(jìn)行分析和修復(fù)。
(3)第三種辦法:contiune; 那就是最壞的情況,忽略錯誤,不處理異常情況

不要使用String字符串加鎖,這樣會導(dǎo)致死循環(huán)產(chǎn)生
請看下面的例子:

package Thread;

/**
 * Created by zhangzheming on 2018/1/15.
 */

public class StringLock {

    public void method(){
        // 使用字符串當(dāng)做對象
        synchronized ("字符串常量"){
            try{
                while (true){
                    System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+"開始");
                    Thread.sleep(1000);
                    System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+"結(jié)束");
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

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

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


        t1.start();
        t2.start();
    }
}

運(yùn)行結(jié)果

按照我們預(yù)想的,啟動兩個線程會在執(zhí)行結(jié)果中產(chǎn)生兩個線程交替進(jìn)行,但是與實(shí)際結(jié)果不相同,這是為什么?

原因在于字符串屬于引用類型,不管什么樣的字符串都是一個類型對象,這樣就導(dǎo)致了只有一個線程存在,回頭想想其實(shí)要解決這個問題,就是滿足synchronized 鎖住的是對象就可以了,修改如下:

package Thread;

/**
 * Created by zhangzheming on 2018/1/15.
 */

public class StringLock {

    public void method(){
        // 使用字符串當(dāng)做對象
        synchronized (new String("字符串常量")){
            try{
                while (true){
                    System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+"開始");
                    Thread.sleep(1000);
                    System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+"結(jié)束");
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

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

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


        t1.start();
        t2.start();
    }
}

運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,740評論 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,815評論 0 11
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,600評論 1 15
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,111評論 1 18
  • 轉(zhuǎn)自:http://blog.csdn.net/jackfrued/article/details/4492194...
    王帥199207閱讀 8,807評論 3 93

友情鏈接更多精彩內(nèi)容