很偶然的机会发现了无锁队列,然后又很偶然的接触到并行编程,虽然还没弄明白内存屏障等问题,但是历史遗留下一小段测试代码,在这段测试代码中我用分别用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,但效率远高于两个线程并发执行.
你丫这函数都不加锁,跑起来肯定乱的一团糟
@丁松 你没看到, 没加锁的是使用的无锁系列函数, 你跑跑看结果会令你惊讶