對於多執行緒訪問同一變數是否需要加鎖的問題,先前大家都討論過。今天用**驗證了一下之前的猜想: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
int
g_test;
int
temp;
bool
g_brunning;
dword
winapi thwriteproc1(
lpvoid
lparam)
return
0;
}
dword
winapi thwriteproc2(
lpvoid
lparam)
return
0;
}
dword
winapi threadproc(
lpvoid
lparam)
sleep(1);
}
return
0;
}
void
ctestmultiyaccessintdlg::onbutton1()
for
(
int
i = 0; i < 50; i++ )
for
(
int
i = 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...