首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WaitForSingleObject与互锁*

WaitForSingleObject与互锁*
EN

Stack Overflow用户
提问于 2013-12-13 10:31:09
回答 2查看 3K关注 0票数 1

在WinAPI下有WaitForSingleObject()和ReleaseMutex()函数对。还有互锁的*()函数族。我决定检查捕获单个互斥变量和交换互锁变量之间的性能。

代码语言:javascript
复制
HANDLE mutex;
WaitForSingleObject(mutex, INFINITE);
// ..
ReleaseMutex(mutex);

// 0 unlocked, 1 locked
LONG lock = 0;
while(InterlockedCompareExchange(&lock, 1, 0))
  SwitchToThread();
// ..
InterlockedExchange(&lock, 0);
SwitchToThread();

我测量了这两种方法之间的性能,发现使用互锁*()大约快38%。为什么会这样呢?

这是我的性能测试:

代码语言:javascript
复制
#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;

LONG interlocked_variable   = 0; // 0 unlocked, 1 locked
int run                     = 1;

DWORD WINAPI thread(LPVOID lpParam)
{
    while(run)
    {
        while(InterlockedCompareExchange(&interlocked_variable, 1, 0))
            SwitchToThread();
        ++(*((unsigned int*)lpParam));
        InterlockedExchange(&interlocked_variable, 0);
        SwitchToThread();
    }

    return 0;
}

int main()
{
    unsigned int num_threads;
    cout << "number of threads: ";
    cin >> num_threads;
    unsigned int* num_cycles = new unsigned int[num_threads];
    DWORD s_time, e_time;

    s_time = GetTickCount();
    for(unsigned int i = 0; i < num_threads; ++i)
    {
        num_cycles[i] = 0;
        HANDLE handle = CreateThread(NULL, NULL, thread, &num_cycles[i], NULL, NULL);
        CloseHandle(handle);
    }
    _getch();
    run = 0;
    e_time = GetTickCount();

    unsigned long long total = 0;
    for(unsigned int i = 0; i < num_threads; ++i)
        total += num_cycles[i];
    for(unsigned int i = 0; i < num_threads; ++i)
        cout << "\nthread " << i << ":\t" << num_cycles[i] << " cyc\t" << ((double)num_cycles[i] / (double)total) * 100 << "%";
    cout << "\n----------------\n"
        << "cycles total:\t" << total
        << "\ntime elapsed:\t" << e_time - s_time << " ms"
        << "\n----------------"
        << '\n' << (double)(e_time - s_time) / (double)(total) << " ms\\op\n";

    delete[] num_cycles;
    _getch();
    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-13 10:42:40

WaitForSingleObject不一定要更快。它涵盖了更广泛的同步场景,特别是您可以等待不属于流程的句柄,因此进程间同步。考虑到所有这些因素,根据你的测试结果,它只慢了38%。

如果您拥有流程中的所有内容和每毫秒的计数,那么InterlockedXxx可能是一个更好的选择,但它绝对不是绝对优越的选择。

此外,您可能需要查看Slim阅读器/作家(SRW)锁 API。您可能会完全基于InterlockedXxx构建一个类似的类/函数,其性能略好一些,但关键是,通过SRW,您可以随时使用它,具有文档化的行为、稳定的性能和良好的性能。

票数 4
EN

Stack Overflow用户

发布于 2013-12-13 10:48:39

您并不是在比较等效的锁,因此性能如此不同并不令人惊讶。

互斥锁允许跨进程锁定,这可能是最昂贵的锁定方式之一,因为它提供了灵活性。当你封锁一个锁时,它通常会让你的线程进入睡眠状态,这在你被唤醒之前不需要cpu。这允许其他代码使用cpu。

InterlockedCompareExchange()代码是一个简单的自旋锁。你会消耗CPU等待你的锁。

根据我的测试,您还可能希望查看临界截面 (比Mutex更少的开销)和苗条读者/作家锁 (根据我的测试,它们可以用于互斥,如果总是获得独占锁,并且提供比关键部分更快的性能,用于无争议的使用)。

你可能还想读肯尼·克尔的“Windows与C++同步的演变”和Preshing的锁相关的东西,这里这里

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20564229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档