天天看點

在 web 業務開發中究竟該如何使用鎖?(上)案例1 為什麼鎖可以解決線程安全問題

案例

  • demo 類
  • 在 web 業務開發中究竟該如何使用鎖?(上)案例1 為什麼鎖可以解決線程安全問題
  • 起倆線程分别執行add、compare
  • 在 web 業務開發中究竟該如何使用鎖?(上)案例1 為什麼鎖可以解決線程安全問題
  • 乍一看,a、b“同時”自增,應該一直相等,compare中的判斷不會為true。
  • 但是看日志:不僅有a<b成立,a>b有時也為 true。
  • 在 web 業務開發中究竟該如何使用鎖?(上)案例1 為什麼鎖可以解決線程安全問題
  • 評論裡肯定有人在這裡就笑了,這是你的代碼太垃圾,操作兩個字段a和b,有線程安全問題,應該為add方法加上鎖,確定a和b的++是原子性的,就不會錯了。

那麼,就在add方法加鎖看看?

public synchronized void add()      

但,加鎖後問題并沒有解決。

1 為什麼鎖可以解決線程安全問題

因為隻有一個線程可拿到鎖,是以加鎖後的代碼中的資源操作線程安全。

但該案例中的 add 始終隻有一個線程在操作,顯然隻為 add 加鎖無意義。

是以因為兩個線程是交錯執行add和compare中的業務邏輯,而且這些業務邏輯不是原子性的:a++和b++操作中可以穿插在compare方法的比較代碼中;

a<b這種比較操作在位元組碼層面是三步,即不是原子的:

  1. 加載a
  2. 加載b
  3. 比較

應該為add和compare都加鎖,確定add執行時,compare無法讀取a和b:

public synchronized void add()
public synchronized void compare()      

是以,使用鎖一定要梳理清楚線程、業務邏輯和鎖三者關系。

繼續閱讀