對象及變量的併發訪問

關鍵字sychronized&Volatile的特性

sychronized同步方法

  • 使用synchronized修飾可以保證被修飾對象或方法的安全性,同一時間保證只有一個線程佔有或使用它們。

  • 關鍵字synchronized取得的鎖都是對象鎖,如何沒有其它線程獲得了該對象鎖,那麼該對象可以獲得該對象鎖,否則必須等待其它對象釋放了該對象鎖方可獲得。不同的對象實例擁有不同的對象鎖;

  • 在對象鎖被其他線程取得,仍然能訪問該對象的非同步方法(asynchronized);

  • 關鍵字synchronized擁有鎖重入的功能,即在使用synchronized時,當一個線取得了一個對象的對象鎖,可以再次獲得該對象的鎖,即使在沒有是否當前對象鎖的狀態下;(如果沒有這個特性在獲得對象鎖的情況下再次申請對象鎖會造成死鎖)鎖重入展示如下:

    //Service.class
    public class Service{
      synchronized public void service1(){
          System.out.println("service1");
          service2();
      }
      synchronized public void service2(){
          System.out.println("service2");
          service3();
      }
      synchronized public void service3(){
          System.out.println("service3");
      }
    }
    //MyThread.class
    public class MyThread extends Thread {
      public void run(){
          Service service =new Service();
          service.service1();
      }
    }
    //Mamin.class
    import static java.lang.Thread.sleep;
    
    public class Main{
      public static void main(String args[]){
          MyThread b=new MyThread();
          b.start();
      }
    }
    /*
    *輸出結果
    service1
    service2
    service3
    */
  • sychronized鎖中的代碼執行出現異常,會自動釋放鎖;

  • sychronized可以保證執行的原子性和可見性,在Java內存模型中,synchronized規定,線程在加鎖時,先清空工作內存→在主內存中拷貝最新變量的副本到工作內存→執行完代碼→將更改後的共享變量的值刷新到主內存中→釋放互斥鎖。

  • 對於(synchronized(對象){代碼塊})synchronized鎖住的是括號裏的對象,而不是代碼。對於非static的synchronized方法,鎖的就是對象本身也就是this(pubilc sychronized void test(){代碼塊})。

關鍵字Volatile

  • volatile可以保證內存的可見性

  • volatile不需要加鎖,比Sychronized更輕級,並不會阻塞線程

  • volatile標誌的變量不會被編譯器優化;

  • volatile只能修飾變量,而sychronized可以修飾變量和代碼塊,方法;

    經過volitile修飾的變量在內存中的工作模式如下

這裏寫圖片描述

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