秦曉波著的編寫高品質代碼-改善Java程式的151個建議一書中的線程解釋錯誤.

來源:互聯網
上載者:User

標籤:

位置: 建議127: Lock與synchronized是不一樣的

首先在概念上糾正這一篇內容:

援引Java源碼中關於ReentrantLock的開篇說明:

 * A reentrant mutual exclusion {@link Lock} with the same basic
 * behavior and semantics as the implicit monitor lock accessed using
 * {@code synchronized} methods and statements, but with extended
 * capabilities.

根據說明: 兩個加鎖方式是具有相同的基礎行為和語義的,僅僅是表現形式上和功能擴充性方面的差別,所以該建議理論是錯誤的.

 以下程式碼片段的執行差異和原作者的解釋錯誤主要出現在以下幾個方面:

1.  ReentrantLock和synchronized 都是對象級所,而沒有一個是類級的,因此都只能作用到代碼所影響的具體對象上去.

  如 synchronized public void read(){

    // some executing code region

  } 其實是隱式鎖定了this;

  等價於:

  Lock lock = new ReentrantLock();

  public void read(){

    lock.lock();

    try{

      // some executing code region

    }finally{

      lock.unlock();

    }

  }

  兩者的區別是一個monitorthis, 一個monitor lock對象.

比較特殊的情況是:

synchronized publi static execute(){

  

}

該類對象鎖定的是 .class對象.

 

下文中的不一致性主要出現在對"A"的synchronized鎖定上,

常量字串對象在整個生命週期內是全域唯一的,因此,對"A"的所是全域生效的,不僅僅在次類內部,及時全域任何對synchronized("A")都會產生同步效果,這裡違反了封閉原則,因此具有巨大的編程風險.

 

援引代碼錯誤:

該篇引用了兩段代碼來說明兩種方式的行為不一致性.

在這裡簡單地列舉並指出問題所在:

class1 : lock

/*****************************************************************************/

class Task {

  public void doSomething(){

    try{

      Thread.sleep(2000);

    }catch(Exception e){

      // 異常處理

    }

    StringBuilder sb = new StringBuilder();

    // 線程名稱:

    sb.append(" 線程名稱: " + Thread.currentThread().getName());

    // 已耗用時間戳

    sb.append(",執行時間: " + Calendar.getInstance().get(13) + " s");

    System.out.println(sb.toString());

  }

}

 

/****************************************************************************/

class TaskWithLock extends Task implements Runnable{

  private final Lock lock = new ReentrantLock();

  @Override

  public void run(){

    try{

      // 開始鎖定

      lock.lock();

      doSomething();

    }finally{

      // 釋放鎖

      lock.unlock();

    }

  }

}

/***************************************************************************/

class TaskWithSync extends Task implements Runnable{

  @Override

  public void run(){

    // 內部索

    synchronized("A"){

      doSomething();

    }

  }

}

 

 

public static void runTasks(Class<? extends Runnable> clazz) throws Exception {

  try{

  ExecutorService es = Executors.newCachedThreadPool();

  System.out.println("***開始執行" + clazz.getSimpleName() + " 任務已執行完畢-----------------\n");

  // 啟動三個線程

  for ( int i=0; i<3 ; i++){

    es.submit(clazz.newInstance());

  }

  TimeUnit.SECONDS.sleep(10);

  System.out.println("--------" + clazz.getSimpleName() + " 任務執行完畢------\n");

   // 關閉執行器

  }finally{

    es.shutdown();

  }

}

 

秦曉波著的編寫高品質代碼-改善Java程式的151個建議一書中的線程解釋錯誤.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.