当前位置: 首页 > 知识库问答 >
问题:

同一互斥锁上有多个锁,一个永远锁定

黄飞翮
2023-03-14

在我的程序中,我有一个互斥锁和两个线程。其中一个线程经常获取锁。另一个线程试图获取,但必须永远等待。

是否会因为释放锁后很快就获得了锁,而另一个线程没有机会获得锁?互斥总是给每个人一个机会吗?如果不是,什么是好的解决方案?(某种FIFO锁?)

我使用的是std::mutex和std::lock\u guard

问题扩展seccpur指出,std::condition\u变量可以解决这个问题。三个线程如何伸缩?std::condition\u变量是否确保每个线程都有一个回合?假设您使用notify\u one()。

共有3个答案

范侯林
2023-03-14

使用std::互斥锁std::lock_guardstd::unique_lock(读取器)和std::condition_variable示例。_mutexLockCondition、_mutexObject和_dataContainer在ReaderClass和WriterClass之间共享。

试图对实际的数据容器有点含糊不清,所以由您决定。

std::shared_ptr< Data > ReaderClass::read()
{
    std::unique_lock< std::mutex > lock( _mutexObject );

    // handle spurious wakeup from waitForMessageNotification
    while( _dataContainer.empty() )
    {
        if( waitForMessageNotification( lock ) )
        {
            // timeout occurred, return nullptr to prevent blocking
            return nullptr;
        }
    }

    return getDataFromContainer();
}

bool ReaderClass::waitForNotification( unique_lock< mutex > & lock )
{
    //_mutexLockCondition is a std::condition_variable
    return _mutexLockCondition.wait_for( lock, std::chrono::milliseconds( 100 ) )
                                            == std::cv_status::timeout;
}


void WriterClass::write( std::shared_ptr< Data > dataPtr )
{
    std::lock_guard< mutex > lock( _mutexObject );

    addDataToContainer( dataPtr );

    _mutexLockCondition.notify_one();
}
桓瀚
2023-03-14

利用seccpur的提示,我想出了以下解决方案来防止耗尽单个线程。

#include <condition_variable>
#include <mutex>
#include <atomic>

class NoStarveLock
{
    std::condition_variable condition;
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
    std::mutex conditionLock;
public:
    void lock()
    {
        std::unique_lock<std::mutex> lck(conditionLock);
        while (flag.test_and_set()) // multiple threads can wake up at the same time, so use a set+test
        {
            condition.wait(lck); // wait for a wakeup
        }
    }

    void unlock()
    {
        std::unique_lock<std::mutex> lck(conditionLock);
        flag.clear();
        condition.notify_all();
    }
};
陈正业
2023-03-14

互斥不能保证给每个人平等的机会。因此,一个线程可能会使另一个线程饥饿。您可以尝试的第一件事是插入std::this\u thread::yield(),看看是否有帮助。如果这没有帮助,那么您的代码一定有逻辑错误。发布部分代码,我们可以帮助您进一步诊断。

 类似资料:
  • 本文向大家介绍互斥锁死锁,包括了互斥锁死锁的使用技巧和注意事项,需要的朋友参考一下 死锁可以在使用互斥锁的多线程Pthread程序中发生。让我们看看它如何发生。未锁定的互斥锁由pthread_mutex_init()函数初始化。 使用pthread_mutex_lock()和pthread_mutex_unlock()获取并释放互斥锁。如果线程尝试获取锁定的互斥锁,则对pthread_mutex_

  • Go语言包中的 sync 包提供了两种锁类型:sync.Mutex 和 sync.RWMutex。 Mutex 是最简单的一种锁类型,同时也比较暴力,当一个 goroutine 获得了 Mutex 后,其他 goroutine 就只能乖乖等到这个 goroutine 释放该 Mutex。 RWMutex 相对友好些,是经典的单写多读模型。在读锁占用的情况下,会阻止写,但不阻止读,也就是多个 gor

  • Introduction This is the fourth part of the chapter which describes synchronization primitives in the Linux kernel and in the previous parts we finished to consider different types spinlocks and semap

  • 问题内容: 帮助客户解决他们遇到的问题。我更多地是sysadmin / DBA的人,所以我在努力帮助他们。他们说这是内核/环境中的错误,在我坚持要在他们的代码中或寻求供应商对OS的支持之前,我试图证明或证明这一点。 发生在Red Hat和Oracle Enterprise Linux 5.7(和5.8)上,应用程序用C ++编写 他们遇到的问题是主线程启动一个单独的线程来执行可能长时间运行的TCP

  • 9.2. sync.Mutex互斥锁 在8.6节中,我们使用了一个buffered channel作为一个计数信号量,来保证最多只有20个goroutine会同时执行HTTP请求。同理,我们可以用一个容量只有1的channel来保证最多只有一个goroutine在同一时刻访问一个共享变量。一个只能为1和0的信号量叫做二元信号量(binary semaphore)。 gopl.io/ch9/bank

  • 问题内容: 线程都是可运行的,并且它们拥有相同的锁。两个线程都可以运行时,它们可以锁定相同的地址吗?那是JRE错误吗? 问题答案: 该问题仅存在于线程转储中。实际上,在任何时间点,锁都仅由一个线程持有。但是,线程转储显示两个具有相同锁的不同线程,因为它不是原子的。 可以使用以下程序轻松重现该行为: