對於「多執行緒訪問同乙個變數是否需要加鎖」的研究

2021-06-21 22:02:05 字數 3610 閱讀 3592

對於多執行緒訪問同一變數是否需要加鎖的問題,先前大家都討論過。今天用**驗證了一下之前的猜想:32位cpu與記憶體的最小交換資料為4位元組/次,這也是結構體要對齊4位元組的原因。在物理上,cpu對於同一4位元組的記憶體單元,不可能寫2個位元組的同時,又讀了3位元組。

測試環境為:

xeon 2cpu*2

windows7

採用50,50,50執行緒交叉讀寫,試驗**如下:

c/c++ code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

intg_test;

inttemp;

boolg_brunning;

dwordwinapi thwriteproc1(lpvoidlparam)

return0;

}

dwordwinapi thwriteproc2(lpvoidlparam)

return0;

}

dwordwinapi threadproc(lpvoidlparam)

sleep(1);

}

return0;

}

voidctestmultiyaccessintdlg::onbutton1()

for(inti = 0; i < 50; i++ )

for(inti = 0; i < 50; i++ )

}

測試方法:

改變g_test的型別,給g_test賦予不同的值(不要超過型別的上限值)

測試現象:

當g_test為int,short char時,不存在多執行緒交叉讀寫錯誤的問題

當g_test為double, float, __int64時,存在多執行緒交叉讀寫錯誤的問題,對於__int64,當賦值小於0xffffffff時不出錯,當大於0xffffffff時出錯

當g_test為cstring時,存在交叉讀寫錯誤,有時候程式崩潰

另:不加sleep(1)機器卡死過,cpu佔用率達到100%,4個核心佔用率全滿,可以保證執行在多核環境下

現象分析:

(1)int short char均為小於4位元組的連續記憶體塊,cpu一條指令就可以讀寫它們的值,cpu不可能同乙個時間執行兩條指令

(2)double為8位元組,如果寫執行緒先寫了4位元組,讀執行緒讀了8位元組,這自然導致資料被破壞

(3)float也為4位元組,我也不是太清楚為什麼不行,可能是vc對浮點數的處理比較特殊有關,浮點數具有複雜記憶體結構

(4)__int64為8位元組,存在和(2)相同的情況,如果__int64小於等於0xffffffff,相當於只改變了低4位元組,因此就沒有問題

(5)cstring為類型別,具有複雜結構,顯然不行

結論:1.對於int,short,char,bool等小於等於4位元組的簡單資料型別,如果無邏輯上的先後關係,多執行緒讀寫可以完全不用加鎖

2.儘管float為4位元組,多執行緒訪問時也需要加鎖

3.對於大於4位元組的簡單型別,比如double,__int64等,多執行緒讀寫必須加鎖。

4.對於所有複雜型別,比如類,結構體,容器等型別必須加鎖

儘管對int等型別的多執行緒讀寫不需要加鎖,但是邏輯上有必要加鎖的還是應該加鎖

例如:對於乙個多執行緒訪問的全域性變數int g_test

int count = g_test/1024;

int mod = g_test%1024;

由於是兩條語句,執行完第一條之後,別的執行緒很可能已經修改了g_test的值,如果希望這兩條語句執行時,g_test不發生變化,就必須加鎖,以保證兩條語句執行的整體性。

lock();

int count = g_test/1024;

int mod= g_test%1024;

unlock();

如果不加鎖,也可以改為先儲存到乙個臨時變數裡

int temp = g_test;

int count = temp/1024;

int mod = temp%1024;

C 多執行緒如何訪問同乙個資料

在多執行緒中,為了使資料保持一致性必須要對資料或是訪問資料的函式加鎖,在資料庫中這是很常見的,但是在程式中大部分都是單執行緒的程式,所以沒有加鎖的必要,但是在多執行緒中,為了保持資料的同步,一定要加鎖。在framework中已經為我們提供了三個加鎖的機制,分別是monitor類 lock關鍵字和mu...

多執行緒併發同乙個表問題

table for update for update of a.id a1.有where條件時,鎖定條件中指定的資料行 行級封鎖 2.無where條件是,鎖定表a 表級封鎖 1.有where條件時,鎖定條件中指定的資料行 行級封鎖 2.無where條件是,鎖定表a 表級封鎖 a,b直接封鎖a,b表...

python高階之多執行緒對同乙個全域性變數的處理方法

通常情況下 from threading import thread global num 0 def func1 global global num for i in range 1000000 global num 1 print func1 global num s global num de...