static synchronized方法和synchronized方法的區別和聯繫-1(相同鎖下的訪問比較)

1.1  synchronized修飾的普通方法---------被同一個對象實例訪問

package com.ljf.mianshi.demo.mainshithread;

public class TestJd {
    public static void main(String args[]){
        JDSB jdsb=new JDSB();
        JDSB jdsb2=new JDSB();
        new Thread(new ThreadA(jdsb),"A").start();
        new Thread(new ThreadB(jdsb),"B").start();

    }

}

package com.ljf.mianshi.demo.mainshithread;

public class JDSB {


    public  synchronized void   sayA() {
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
    }


}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadA implements Runnable {
    JDSB jdsb=null;
    public ThreadA(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadB implements Runnable {
    JDSB jdsb=null;
    public ThreadB(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}

結果:

我是線程:A我開始執行sayA
我是線程:A我離開sayA
我是線程:B我開始執行sayA
我是線程:B我離開sayA
結論:synchronized修飾普通方法,使用同一對象訪問,那麼結果是同步的。

1.2  synchronized修飾的普通方法---------被不同對象實例訪問

package com.ljf.mianshi.demo.mainshithread;

public class TestJd {
    public static void main(String args[]){
        JDSB jdsb=new JDSB();
        JDSB jdsb2=new JDSB();
        new Thread(new ThreadA(jdsb),"A").start();
        new Thread(new ThreadB(jdsb2),"B").start();

    }

}
package com.ljf.mianshi.demo.mainshithread;

public class JDSB {


    public  synchronized void   sayA() {
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
    }


}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadA implements Runnable {
    JDSB jdsb=null;
    public ThreadA(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadB implements Runnable {
    JDSB jdsb=null;
    public ThreadB(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}


結果:

我是線程:B我開始執行sayA
我是線程:A我開始執行sayA
我是線程:B我離開sayA
我是線程:A我離開sayA
結論:synchronized修飾普通方法,使用不同對象訪問,那麼結果是異步的。不同的對象使用各自的鎖。

比較1.1和1.2得出的結論爲:synchronized修飾不加static的普通方法時使用的鎖是this對象,使用同一對象訪問,那麼結果是同步的,使用的是同一把鎖,使用不同對象訪問,那麼結果是異步的。不同的對象使用各自的鎖,不同的對象沒有競爭關係;

1.3  synchronized修飾static的方法---------被同一對象實例訪問

package com.ljf.mianshi.demo.mainshithread;

public class TestJd {
    public static void main(String args[]){
        JDSB jdsb=new JDSB();
        JDSB jdsb2=new JDSB();
        /** synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,
         * 而Class鎖可以對類的所有對象實例起作用
         */
        new Thread(new ThreadA(jdsb),"A").start();
        new Thread(new ThreadB(jdsb),"B").start();

    }

}
package com.ljf.mianshi.demo.mainshithread;

public class JDSB {


    public static synchronized void   sayA() {
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
    }


}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadA implements Runnable {
    JDSB jdsb=null;
    public ThreadA(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}

package com.ljf.mianshi.demo.mainshithread;

public class ThreadB implements Runnable {
    JDSB jdsb=null;
    public ThreadB(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}

結果:

我是線程:A我開始執行sayA
我是線程:A我離開sayA
我是線程:B我開始執行sayA
我是線程:B我離開sayA

1.4  synchronized修飾static的方法---------被不同對象實例訪問

package com.ljf.mianshi.demo.mainshithread;

public class TestJd {
    public static void main(String args[]){
        JDSB jdsb=new JDSB();
        JDSB jdsb2=new JDSB();
        /** synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,
         * 而Class鎖可以對類的所有對象實例起作用
         */
        new Thread(new ThreadA(jdsb),"A").start();
        new Thread(new ThreadB(jdsb2),"B").start();
       

    }

}
package com.ljf.mianshi.demo.mainshithread;

public class JDSB {


    public static synchronized void   sayA() {
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
    }


}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadA implements Runnable {
    JDSB jdsb=null;
    public ThreadA(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}
package com.ljf.mianshi.demo.mainshithread;

public class ThreadB implements Runnable {
    JDSB jdsb=null;
    public ThreadB(JDSB jdsb) {
        this.jdsb=jdsb;
    }

    @Override
    public void run() {
        jdsb.sayA();
    }
}

經過1.3和1.4比較可得:而兩個對象是同一個class文件,所以使用的是一個鎖。

synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,而Class鎖可以對類的所有對象實例起作用,類鎖就是要控制類的所有實例的併發訪問,這個類所有的對象競爭一把鎖。

參考地址:

https://blog.csdn.net/ROAOR1/article/details/88845700

https://www.cnblogs.com/hongdalin/p/11492192.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章