很偶然的机会发现了无锁队列,然后又很偶然的接触到并行编程,虽然还没弄明白内存屏障等问题,但是历史遗留下一小段测试代码,在这段测试代码中我用分别用lock-free或lock-based方式将一个变量进行自增, 效果竟然差的惊人, 肉眼都能感觉到效率不止差了至少四倍之多。下面看代码:
#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,但效率远高于两个线程并发执行.
你丫这函数都不加锁,跑起来肯定乱的一团糟
@丁松 你没看到, 没加锁的是使用的无锁系列函数, 你跑跑看结果会令你惊讶