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