深入理解使用synchronized同步方法和同步代碼塊的區別


一.代碼塊和方法之間的區別

首先需要知道代碼塊和方法有什么區別:

構造器和方法塊,構造器可以重載也就是說明在創建對象時可以按照不同的構造器來創建,那么構造器是屬於對象,而代碼塊呢他是給所有的對象初始化的。底下看一個列子:

public class Constructor_Methodblock {
    private int num;
    private String str;
    //構造器
    public Constructor_Methodblock(int num,String str){
        System.out.println("\n************構造器****************");
        System.out.println("在進入構造器之前成員變量的值為num:"+this.num+"str: "+this.str);
        this.str=str;
        this.num=num;
        System.out.println("賦值之后num為"+num+"str為"+str);
    }
    //方法塊
    {
        System.out.println("\n************代碼塊****************");
        System.out.println("在進入方法塊之前成員變量的值為num:"+num+"str: "+str);
        num=1;
        str="li";
        System.out.println("賦值之后num為"+num+"str為"+str);
    }

    public static void main(String[] args) {
        new Constructor_Methodblock(2,"fei");
    }
}

 結果為:

 發現代碼塊比構造器早執行,而且代碼塊是所有的對象都要執行的。

 現在我們對代碼塊和方法有了一定的了解,那么同步方法有什么缺點使得我們需要同步代碼塊呢?

二.同步方法的缺點

來想象一個這樣的情況:一個方法其中有一部分是需要計算數據花費時間不是那么長但是還有一部分他不需要處理數據但是他需要花費大量的時間,那么如果我們直接將這個方法同步化會導致整體的代碼性能下降,而我們僅僅將這個計算數據部分同步保證共享數據計算沒有問題,那么代碼性能是不是就上去了呢?

來看直接同步化方法:

public class SynFun extends Thread {
    private int num=10;//共享數據
    @Override
     public void run(){
        try {
            this.fun();//調用同步方法
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void fun() throws InterruptedException {
        //使用睡眠來模擬一下復雜但是對數據處理沒有關系的部分,睡眠三秒
        Thread.sleep(3000);
                System.out.println("修改前的num為"+num);
                num--;
                System.out.println("修改后的num為"+num);
        System.out.println("*************");
    }

    public static void main(String[] args) {

        SynFun synFun=new SynFun();
        Thread t1=new Thread(synFun);
        Thread t2=new Thread(synFun);
        t1.start();
        t2.start();

    }
}

結果為:出現結果時,先等待了三秒出現了第一個結果,在等待了三秒又出現了第二個結果。

改進一下:

public  void fun() throws InterruptedException {
        //使用睡眠來模擬一下復雜但是對數據處理沒有關系的部分,睡眠三秒
        Thread.sleep(3000);
        synchronized (this){
            System.out.println("修改前的num為"+num);
            num--;
            System.out.println("修改后的num為"+num);
        }
        System.out.println("*************");
    }

 

就是利用同步化代碼塊,將共享數據處理的部分同步起來,而其他的部分就讓他去交叉運行吧。

結果是一樣的,但是出現結果就是三秒以后直接出現兩個答案,說明整體性能直接上去了。

 

 ******************************************************題外話***********************************************************

Java多線程專題已經已經發表了五篇博客了,不少前輩(其實我還是一個大二的學生)都給出了很好的講解和指導,在這里真的非常感謝你們。

1   if(對我的博客感興趣){
2         點贊+關注;
3     }else{
4         沒有else
5     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM