锁对于性能的影响

很偶然的机会发现了无锁队列,然后又很偶然的接触到并行编程,虽然还没弄明白内存屏障等问题,但是历史遗留下一小段测试代码,在这段测试代码中我用分别用lock-free或lock-based方式将一个变量进行自增, 效果竟然差的惊人, 肉眼都能感觉到效率不止差了至少四倍之多。下面看代码:

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
#include <Windows.h>
 
#define LOCK_FREE       1
 
int cnt;
HANDLE hMutex;
 
static DWORD WINAPI work_thread(void *param)
{
        int i;
        for (i = 0; i < 1000000; i++) {
                #if LOCK_FREE
                //WaitForSingleObject(hMutex, -1);
                InterlockedIncrement((unsigned long *)&cnt);
                //ReleaseMutex(hMutex);
                #else
                WaitForSingleObject(hMutex, -1);
                cnt++;
                ReleaseMutex(hMutex);
 
                #endif
        }
 
        return 0;
}
 
HANDLE thread_begin(int a)
{
        HANDLE hThread = CreateThread(NULL, 0, work_thread, (void *)a, 0, NULL);
 
        return hThread;
 
        return 0;
}
 
 
int main(int argc, _TCHAR* argv[])
{
        HANDLE h1, h2;
 
        hMutex = CreateMutex(NULL, FALSE, NULL);
 
        h1 = thread_begin(0);
        h2 = thread_begin(1);
 
        WaitForSingleObject(h1, -1);
        WaitForSingleObject(h2, -1);
 
        printf("%dn", cnt);
 
        return 0;
}

在这里我使用LOCK_FREE宏来进行切换lock-free方式还是lock-based方式,虽然没有计算时间,但是肉眼都能大概比较出效率至少差了四倍。另外有一点要说的是,这里只是开了两个线程,而且只做了变量自增而已,试想在其他高并发的场合,那么lock-based效率或许将远低于现在的测试情况,所以锁是效率的大敌之一。当然我现在还不太敢用无锁,因为我还没有搞懂什么时间用内存屏障。

————————————————————————–
为了证明是由于资源冲突而不是函数调用拖效率的后腿,可以将main函数中的两句改为如下:

h1 = thread_begin(0);
Sleep(1000);
h2 = thread_begin(1);

Sleep(1000)是为了等第一个线程跑完,这样两个线程跑的次数一样,但是将不再会产生资源冲突, 而且可以看到就算我们延时了1s,但效率远高于两个线程并发执行.

《锁对于性能的影响》有3条评论

发表评论

+ thirty eight = forty three