c++ - 在 C++11 中创建一个保留锁定尝试顺序的锁

标签 c++ multithreading c++11 locking

有没有办法确保被阻塞的线程按照被阻塞的顺序唤醒?我在某处读到这将被称为“强锁”,但我没有找到任何资源。

在 Mac OS X 上,可以设计一个 FIFO 队列来存储阻塞线程的所有线程 ID,然后使用漂亮的函数 pthread_cond_signal_thread_np() 来唤醒一个特定的线程 - 这显然不是-标准和非可移植。

我能想到的一种方法是使用类似的队列,并在 unlock() 点向所有线程发送 broadcast() 并让它们检查哪一个是下一个。
但这会导致大量开销。

解决该问题的一种方法是将 packaged_task 发送到队列并让它按顺序处理它们。但这对我来说更像是一种解决方法而不是解决方案。

编辑:
正如评论所指出的,这个问题听起来可能无关紧要,因为原则上没有保证锁定尝试的顺序。
作为澄清:

我有一个我称之为 ConditionLockQueue 的东西,它与 Cocoa 库中的 NSConditionLock 类非常相似,但它维护一个阻塞线程的 FIFO 队列,而不是一个或多或少的随机池。

基本上任何线程都可以“排队”(有或没有特定“条件”的要求 - 一个简单的整数值 - 要满足)。然后线程被放置在队列中并阻塞,直到它是队列中满足条件的最前面的元素。

这提供了一种非常灵活的同步方式,我发现它在我的程序中非常有用。
现在我真正需要的是一种唤醒具有特定 id 的特定线程的方法。
但这些问题几乎都是一样的。

最佳答案

构建一个使用编号票证的锁对象非常容易,以确保其完全公平(按照线程首先尝试获取锁的顺序授予锁):

#include <mutex>
#include <condition_variable>

class ordered_lock {
    std::condition_variable  cvar;
    std::mutex               cvar_lock;
    unsigned int             next_ticket, counter;
public:
    ordered_lock() : next_ticket(0), counter(0) {}
    void lock() {
        std::unique_lock<std::mutex> acquire(cvar_lock);
        unsigned int ticket = next_ticket++;
        while (ticket != counter)
            cvar.wait(acquire);
    }
    void unlock() {
        std::unique_lock<std::mutex> acquire(cvar_lock);
        counter++;
        cvar.notify_all();
    }
};

编辑

修正奥拉夫的建议:

#include <mutex>
#include <condition_variable>
#include <queue>

class ordered_lock {
    std::queue<std::condition_variable *> cvar;
    std::mutex                            cvar_lock;
    bool                                  locked;
public:
    ordered_lock() : locked(false) {};
    void lock() {
        std::unique_lock<std::mutex> acquire(cvar_lock);
        if (locked) {
            std::condition_variable signal;
            cvar.emplace(&signal);
            signal.wait(acquire);
        } else {
            locked = true;
        }
    }
    void unlock() {
        std::unique_lock<std::mutex> acquire(cvar_lock);
        if (cvar.empty()) {
            locked = false;
        } else {
            cvar.front()->notify_one();
            cvar.pop();
        }
    }
};

关于c++ - 在 C++11 中创建一个保留锁定尝试顺序的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14792016/

相关文章:

c++ - 可变参数模板扩展中的函数调用顺序

c++ - std::vector 在返回之前被自动清除

c++ - c_str() 的要求是否使修改非法?

c++ - 如何卡住一个变量,因为它第一次分配?

java - JOptionPane 打开时是否可以暂停当前线程?

multithreading - 纯 Swift 并发

c# - 等待/异步并跳出框框

c++ - 理解右值引用

c++ - 右值参数的模板类型推导

c++ - const 引用作为返回值如何在 C++ 中工作