c++ - 释放锁时的线程调度

标签 c++ multithreading mutex

解锁互斥体时,我的期望是调度程序检查当前尝试锁定该互斥体的其他线程,然后执行这些等待线程之一。我编写了一个测试程序(参见下面的代码),其中有 2 个线程都试图在循环中获取相同的互斥体并执行一些工作(休眠 1 毫秒)。不同之处在于,一个线程 t1 在解锁和尝试重新获取互斥体之间等待一小会儿,而另一个线程 t2 则不会。我预计两个线程获取互斥锁的次数大约相同。然而,在 Windows 上,t1 通常仅获取互斥锁一次,而其他线程则获取数百次。在 Linux 上,行为有所不同,两个线程使用 t2 完成的工作大约是两倍。为什么 Windows 上的 t1 几乎从不获取互斥体?我必须如何修改代码才能实现它?

示例代码:

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>

using namespace std;

int main()
{
    mutex m;
    atomic<bool> go(false);
    int t1Counter = 0, t2Counter = 0;

    thread t1([&] {
        while(!go);
        while(go) {
            this_thread::sleep_for(100us);
            lock_guard<mutex> lg(m);
            this_thread::sleep_for(1ms);
            ++t1Counter;
        }
    });
    thread t2([&] {
        while(!go);
        while(go) {
            lock_guard<mutex> lg(m);
            this_thread::sleep_for(1ms);
            ++t2Counter;
        }
    });

    go = true;
    this_thread::sleep_for(1s);
    go = false;
    t1.join();
    t2.join();

    cout << t1Counter << " " << t2Counter << endl;
}

最佳答案

在 Windows 上,std::mutex 是使用细长的读取器/写入器锁来实现的。此锁实现是不公平的(意味着它不保证等待线程获取锁的顺序)。 Windows 不久前就放弃了公平锁,因为 Microsoft 认为锁保护是比线程饥饿更严重的问题。

您可以在 Microsoft 文档中阅读有关 slim 读取器/写入器锁的更多信息:Slim Reader/Writer (SRW) Locks

Joe Duffy 还在博客中讨论了公平性与锁定车队问题:Anti-convoy locks in Windows Server 2003 SP1 and Windows Vista

关于c++ - 释放锁时的线程调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53434834/

相关文章:

C++ for 循环 : 'i' was not declared in this scope

c++ - 在不更改代码的情况下拆分 .cpp 文件

multithreading - 在Silverlight中,如何使程序在不占用线程的情况下进入休眠状态

c++ - 互斥体上的条件断点未触发

c++ - C++11 mutex 是否只使用静态初始化?

c - ODBC 单连接或每线程一个连接

c++ - boost::managed_shared_memory 可以正确处理 vector 吗?

c++ - vector 迭代器比较

仅当通过文件接收(非用户)输入时才执行的 Java 程序

c++ - std::lock_guard 不会解锁