Java synchronized的使用

須要明確的幾個問題:ide

  • synchronized關鍵字能夠做爲函數的修飾符,也可做爲函數內的語句,也就是平時說的同步方法和同步語句塊。若是 再細的分類,synchronized可做用於instance變量object reference(對象引用)、static函數和class literals(類名稱字面常量)身上。
  • 不管synchronized關鍵字加在方法上仍是對象上,它取得的鎖都是對象,而不是把一段代碼或函數看成鎖――並且同步方法極可能還會被其餘線程的對象訪問。
  • 每一個對象只有一個鎖(lock)與之相關聯。
  • 實現同步是要很大的系統開銷做爲代價的,甚至可能形成死鎖,因此儘可能避免無謂的同步控制。

synchronized關鍵字的做用域有二種:

  1. 某個對象實例內,synchronized aMethod(){}能夠防止多個線程同時訪問這個對象的synchronized方法(若是一個對象有多個synchronized方法,只要一個線 程訪問了其中的一個synchronized方法,其它線程不能同時訪問這個對象中任何一個synchronized方法)。這時,不一樣的對象實例的 synchronized方法是不相干擾的。也就是說,其它線程照樣能夠同時訪問相同類的另外一個對象實例中的synchronized方法;
  2. 某個類的範圍,synchronized static aStaticMethod{}防止多個線程同時訪問這個類中的synchronized static 方法。它能夠對類的全部對象實例起做用。

 

一、使用在方法上synchronized aMethod(){...}函數

  使用相同的 object測試

public  class synchTest {
    private String a= "";
    private List<String> b= new ArrayList<>();

    // 方法一
    public  void job()  {
        System.out.println("job .....");
        synchronized (b){
            System.out.println("job 使用鎖中 ....");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job end.....");
    }
    // 方法二
    public synchronized void job2(){
        System.out.println("job2 .....");
        synchronized (b){
            System.out.println("job22 使用鎖中 ...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job2 end.....");
    }


    public static void main(String[] args) {
        final synchTest rs = new synchTest();
        new Thread() {
            public void run() {
                rs.job();
            }
        }.start();
        new Thread() {
            public void run() {
                rs.job2();
            }
        }.start();
    }
}

結果:
job .....
job 使用鎖中 ....
job2 .....
job end.....
job22 使用鎖中 ...
job2 end.....
View Code

     使用不一樣的objectthis

public  class synchTest {
    private String a= "";
    private List<String> b= new ArrayList<>();

    // 方法一
    public  void job()  {
        System.out.println("job .....");
        synchronized (a){
            System.out.println("job 使用鎖中 ....");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job end.....");
    }
    // 方法二
    public synchronized void job2(){
        System.out.println("job2 .....");
        synchronized (b){
            System.out.println("job22 使用鎖中 ...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job2 end.....");
    }


    public static void main(String[] args) {
        final synchTest rs = new synchTest();
        new Thread() {
            public void run() {
                rs.job();
            }
        }.start();
        new Thread() {
            public void run() {
                rs.job2();
            }
        }.start();
    }
}

結果:
job .....
job 使用鎖中 ....
job2 .....
job22 使用鎖中 ...
job end.....
job2 end.....
View Code

    使用this關鍵詞 spa

public  class synchTest {
    private String a= "";
    private List<String> b= new ArrayList<>();

    // 方法一
    public  void job()  {
        System.out.println("job .....");
        synchronized (this){
            System.out.println("job 使用鎖中 ....");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job end.....");
    }
    // 方法二
    public synchronized void job2(){
        System.out.println("job2 .....");
        synchronized (b){
            System.out.println("job22 使用鎖中 ...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job2 end.....");
    }


    public static void main(String[] args) {
        final synchTest rs = new synchTest();
        new Thread() {
            public void run() {
                rs.job();
            }
        }.start();
        new Thread() {
            public void run() {
                rs.job2();
            }
        }.start();
    }
}

結果:
job .....
job 使用鎖中 ....
job end.....
job2 .....
job22 使用鎖中 ...
job2 end.....
View Code

  結論:線程

  •   synchronized(Object) object相同的狀況下,修飾的內容會同步,等上一個執行完才能執行下一個方法的內容
  •        synchronized(Object) object不相同的狀況下,修飾內容不會同步,兩個方法能夠一塊兒執行
  •         this這個比較特殊,若是先執行修飾this這個方法的內容,會同步,不然 不會同步(能夠測試下)

二、使用在方法內部 synchronized(Oject){...}3d

public  class synchTest {
    // 方法一
    public synchronized   void job()  {
        System.out.println("job .....");
        System.out.println("job 使用鎖中 ....");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("job end.....");
    }
    // 方法二
    public synchronized void job2(){
        System.out.println("job2 .....");
        System.out.println("job22 使用鎖中 ...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("job2 end.....");
    }

    public static void main(String[] args) {
        final synchTest rs = new synchTest();
        new Thread() {
            public void run() {
                rs.job();
            }
        }.start();
        new Thread() {
            public void run() {
                rs.job2();
            }
        }.start();
    }
}

結果:
job .....
job 使用鎖中 ....
job end.....
job2 .....
job22 使用鎖中 ...
job2 end.....
View Code

   結論:code

  • 對象實例內,synchronized aMethod(){}能夠防止多個線程同時訪問這個對象的synchronized方法,在對象內容全部的synchronized 的方法都會同步,必須等上一個方法執行完才能執行下一個方法

 

二、使用在方法內部 synchronized(Oject){...}、synchronized aMethod(){...}混用對象

public  class synchTest {
    public String a = "";
    // 方法一
    public void job()  {
        System.out.println("job .....");
        synchronized (a){
            System.out.println("job 使用鎖中 ....");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }
        System.out.println("job end.....");
    }
    // 方法二
    public synchronized void job2(){
        System.out.println("job2 .....");
        System.out.println("job22 使用鎖中 ...");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("job2 end.....");
    }

    public static void main(String[] args) {
        final synchTest rs = new synchTest();
        new Thread() {
            public void run() {
                rs.job();
            }
        }.start();
        new Thread() {
            public void run() {
                rs.job2();
            }
        }.start();
    }
}
結果:
job .....
job 使用鎖中 ....
job2 .....
job22 使用鎖中 ...
job end.....
job2 end.....
View Code

   結論:blog

  對象實例內 synchronized aMethod(){} 與synchronized(Object)  不會相互同步

相關文章
相關標籤/搜索