释放锁时的线程调度

时间:2018-11-22 16:14:36

标签: c++ multithreading mutex

解锁互斥锁时,我的期望是调度程序检查当前尝试锁定此互斥锁的其他线程,然后执行这些等待的线程之一。我编写了一个具有2个线程的测试程序(请参见下面的代码),这两个线程都试图在一个循环中获取相同的互斥体并做一些工作(休眠1ms)。区别在于,一个线程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;
}

1 个答案:

答案 0 :(得分:3)

在Windows上,std::mutex是使用细长的读取器/写入器锁实现的。此锁实现不公平(这意味着它不保证等待线程将获得锁的顺序)。由于微软认为锁护具比线程匮乏更为严重,Windows早已摆脱了公平锁。

您可以阅读有关Microsoft文档上的细长型读写器锁的更多信息:Slim Reader/Writer (SRW) Locks

乔·达菲(Joe Duffy)还写了关于公平与锁定车队问题的博客:Anti-convoy locks in Windows Server 2003 SP1 and Windows Vista