面試官:單核服務器可以不加鎖嗎?
今天有位同學問了磊哥一個問題,大概的意思是“單核服務器可以不加鎖嗎?”,我覺得很有意思,所以在這里就和各位探討一下:
1. 問題答案
先說我的理解,單核服務器仍然需要加鎖。
因為在單核服務器上也會有線程切換,如果不加鎖,那么線程切換后,另一個線程就可以訪問其他線程未操作完的共享變量,這就會導致操作的共享變量發生數據覆蓋的問題,所以是需要加鎖。
例如,以下案例,線程 T1 和線程 T2 都要執行 i++ 操作,i 的初始值為 0,所以正確的執行結果應該是 2。但如果不加鎖,即使在單核服務器下也會造成數據覆蓋問題,最終的執行結果為 1 的情況,具體執行流程如下:
2. 原因分析
因為 i++ 并不是原子操作,它的執行要分為以下 3 步:
- 查詢 i 的值。
- 執行 i+1 修改操作。
- 將結果賦值給 i 變量。
如果是加鎖操作,那么線程可以一個個執行,首先某一個線程先把 i 修改為 1,然后另一個線程再次基礎上將結果修改為 2。
但如果不加鎖,那么就會導致下面的問題:
線程 1 | 線程 2 | |
t1 | 讀取到 i 的值為 0 | |
t2 | 讀取到 i 的值為 0 | |
t3 | 執行 +1 操作,修改 i 為 1 | |
t4 | 將結果 1 賦值給 i 變量 | |
t5 | 執行 +1 操作,修改 i 為 1 | |
t6 | 將結果 1 賦值給 i 變量 |
從上述執行流程可以看出,即使在單核服務上,依然會發生線程切換的問題。而線程切換就可能會導致數據覆蓋的問題,這就是線程安全問題,所以單核服務器也要加鎖。