1. 程式人生 > 程式設計 >Java Synchronized鎖失敗案例及解決方案

Java Synchronized鎖失敗案例及解決方案

synchronized關鍵字,一般稱之為”同步鎖“,用它來修飾需要同步的方法和需要同步程式碼塊,預設是當前物件作為鎖的物件。

同步鎖鎖的是同一個物件,如果物件發生改變,則鎖會不生效。

鎖失敗的程式碼:

public class IntegerSynTest {

  //執行緒實現Runnable介面
  private static class Worker implements Runnable{

    private Integer num;

    public Worker(Integer num){
      this.num=num;
    }
    @Override
    public void run() {
      
      synchronized (num){
        Thread thread = Thread.currentThread();
        //System.identityHashCode:返回原生的hashCode值,不管Object物件是被重寫;空引用的雜湊程式碼為零
        System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
        num++;
        System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
      }
    }

    public static void main(String[] args) {
      Worker worker = new Worker(1);
      for (int i = 0; i < 5; i++) {
        new Thread(worker).start();
      }
    }
  }
}

鎖失敗的執行結果:

Java Synchronized鎖失敗案例及解決方案

鎖失敗的原因:

1.num++  的  .class  實現是這樣的  Integer integer1 = this.num,integer2 = this.num = Integer.valueOf(this.num.intValue() + 1);

2.檢視 Integer.valueOf()的原始碼

Java Synchronized鎖失敗案例及解決方案

這時發現,它是重新 new出一個新的Integer,這樣的話,每 ++一次,那麼就會產生一個新的物件,而Synchronize鎖是鎖同一個物件,當鎖不同物件時,則會鎖失敗。

解決方法:

Synchronized同步鎖只要鎖的物件不發生改變即可,那麼由此只需要宣告一個物件,不修改它,鎖這一個物件即可(還有其他方法暫不一一列舉,以後也不會列舉了)。

鎖成功的程式碼

public class IntegerSynTest {

  //執行緒實現Runnable介面
  private static class Worker implements Runnable{

    private Integer num;
    /**
     * ---重點看這裡---
     * 宣告要鎖的物件
     * ---重點看這裡---
     */
    private Object object = new Object();

    public Worker(Integer num){
      this.num=num;
    }
    @Override
    public void run() {
      //修改鎖物件
      synchronized (num){
        Thread thread = Thread.currentThread();
        //System.identityHashCode:返回原生的hashCode值,不管Object物件是被重寫;空引用的雜湊程式碼為零
        System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
        num++;
        System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
      }
    }

    public static void main(String[] args) {
      Worker worker = new Worker(1);
      for (int i = 0; i < 5; i++) {
        new Thread(worker).start();
      }
    }
  }
}

鎖成功的執行結果:

Java Synchronized鎖失敗案例及解決方案

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。