标签: condition-variable

轮询无锁队列的最快的无竞争方法是什么?

假设我们有一个单生产者线程单消费者线程无锁队列,并且生产者可能会长时间没有产生任何数据.当队列中没有任何东西时,让消费者线程休眠是有益的(为了节省电力并为其他进程/线程释放CPU).如果队列不是无锁的,解决这个问题的直接方法是让生成线程锁定互斥锁,执行其工作,发出条件变量信号并解锁,并为读取线程锁定互斥锁,等待条件变量,做它的阅读,然后解锁.但是,如果我们使用无锁队列,使用互斥锁的方式完全相同,就会消除我们首先使用无锁队列所获得的性能.

天真的解决方案是让每个插入队列后的生产者锁定互斥锁,发出条件变量信号,然后解锁互斥锁,保持实际工作(插入队列)完全在锁外,并让消费者做同样,锁定互斥锁,等待条件变量,解锁它,将所有内容从队列中拉出,然后重复,保持队列的读取在锁外.这里有一个竞争条件:在读取器拉出队列并进入睡眠状态之间,生产者可能已经将一个项目插入队列中.现在读者将进入睡眠状态,并且可以无限期地保持这种状态,直到生产者插入另一个项目并再次发出状态变量信号.这意味着您偶尔会遇到特定的项目,这些项目似乎需要很长时间才能通过队列.如果您的队列始终处于活动状态,这可能不是问题,但如果它始终处于活动状态,您可能完全忘记了条件变量.

AFAICT解决方案是让生产者的行为与使用常规需求锁定队列的行为相同.它应该锁定互斥锁,插入无锁队列,发出条件变量信号,解锁.但是,消费者的行为应该不同.当它唤醒时,它应立即解锁互斥锁,而不是等到它读取队列.然后它应尽可能多地拉出队列并处理它.最后,只有当消费者想要进入睡眠状态时,它是否应该锁定互斥锁,检查是否有任何数据,然后如果解锁并处理它,或者如果没有,则等待条件变量.这样,互斥锁的争用频率低于锁定队列的频率,但是没有数据仍然留在队列中的睡眠风险.

这是最好的方法吗?还有替代品吗?

注意:通过'最快',我的意思是'最快没有专门核心来反复检查队列',但这不适合标题; p

一种替代方案:使用天真的解决方案,但让消费者等待条件变量,其超时对应于您愿意容忍通过队列的项目的最大延迟.如果所需的超时时间相当短,则可能低于操作系统的最短等待时间,或者仍然消耗过多的CPU.

queue multithreading mutex condition-variable lockless

6
推荐指数
1
解决办法
784
查看次数

Windows条件变量与事件

我们可以使用新的条件变量原语或windows事件来同步WinNT v6.x或更高版本中的线程.考虑以下两种方法,我们希望工作者在main中设置"go"的同时运行,否则它们都应该阻塞.

/*language C code*/
/*Windows Condition Variable*/
int go=0;
CONDITION_VARIABLE cv;
SRWLOCK lock;
void workers()
{
    AcquireSRWLockShared(&lock);
    if(go==0)
    {
        SleepConditionVariableSRW(&cv, &lock, INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
    }
    ReleaseSRWLockShared(&lock);
    /*
    Workers continue...
    */
}
void main()
{
    int i;
    InitializeConditionVariable(&cv);
    InitializeSRWLock(&lock);
    for(i=0;i<10;i++)
    {
        CreateThread(0, 0, workers, 0, 0, 0);
    }
    AcquireSRWLockExclusive(&lock);
    go=1;
    ReleaseSRWLockExclusive(&lock);
    WakeAllConditionVariable(&cv);
}
Run Code Online (Sandbox Code Playgroud)

要么

/*language C code*/
/*Windows Event*/
HANDLE go;
void workers()
{
    WaitForSingleObject(go, INFINITE);
    /*
    Workers continue...
    */
}
void main()
{
    int i;
    go=CreateEvent(0,1,0,0); /*No security descriptor, Manual …
Run Code Online (Sandbox Code Playgroud)

c windows multithreading condition-variable readerwriterlockslim

6
推荐指数
1
解决办法
5828
查看次数

Windows中的CONDITION_VARIABLE; 不会编译

我正在尝试用C++编写一个用Linux编写的程序的windows版本.对于程序是线程安全的,我用pthread_cond_tpthread_cond_wait在Linux版本.这些函数使用互斥锁来帮助确保等待的线程实际上正在等待.

我发现CONDITION_VARIABLE在Windows 中可能会有这个技巧,但我无法弄清楚为什么它不会编译.我得到错误"错误:'CONDITION_VARIABLE'没有命名类型",即使包括所有相关的标题,据我所知.我试着在http://msdn.microsoft.com/en-us/library/ms686903%28v=VS.85%29.aspx上复制粘贴代码,它也不会编译.我正在使用GCC.

关于如何编译这个的任何想法?或任何其他方法,不涉及condition_variables?

c++ windows gcc condition-variable

6
推荐指数
1
解决办法
3798
查看次数

在VS2012中使用C++ 11条件变量

我无法使代码在一个简单的VS2012控制台应用程序中可靠地运行,该应用程序由使用C++ 11条件变量的生产者和使用者组成.我的目标是生成一个小的可靠程序(用作更复杂程序的基础),它使用3参数wait_for方法或者我在这些网站上收集的代码中的wait_until方法:

condition_variable: wait_for, wait_until

我想使用3参数wait_for和下面的谓词,除非它需要使用类成员变量对我以后最有用.我只在运行一分钟后收到"访问冲突写入位置0x_ _ "或"无效参数已传递给服务或功能"作为错误.

steady_clock和2参数wait_until是否足以替换3参数wait_for?我也试过这个没有成功.

有人可以展示如何使用下面的代码无限期地运行,没有错误或奇怪的行为,从夏令时或互联网时间同步的挂钟时间的变化?

链接到可靠的示例代码可能同样有用.

// ConditionVariable.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>
#include <atomic>

#define TEST1

std::atomic<int> 
//int 
    qcount = 0; //= ATOMIC_VAR_INIT(0);

int _tmain(int argc, _TCHAR* argv[])
{
    std::queue<int> produced_nums;
    std::mutex m;
    std::condition_variable cond_var;
    bool notified = false;
    unsigned int count = 0;

    std::thread producer([&]() {
        int i = 0;
        while (1) …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading condition-variable c++11 visual-studio-2012

6
推荐指数
2
解决办法
3027
查看次数

std :: condition_variable虚假阻塞

如您所知,应该在循环中调用条件变量以避免虚假唤醒.像这样:

while (not condition)
    condvar.wait();
Run Code Online (Sandbox Code Playgroud)

如果另一个线程想要唤醒等待线程,则必须将condition标志设置为true.例如:

condition = true;
condvar.notify_one();
Run Code Online (Sandbox Code Playgroud)

我想知道,这种情况是否有可能阻止条件变量:

1)等待线程检查条件标志,发现它等于FALSE,因此,它将进入condvar.wait()例程.

2)但就在此之前(但是在条件标志检查之后)等待线程被内核抢占(例如,因为时隙到期).

3)此时,另一个线程想要通知等待线程有关条件.它将条件标志设置为TRUE并调用condvar.notify_one();

4)当内核调度程序再次运行第一个线程时,它进入condvar.wait()例行程序,但通知已经丢失.

因此,等待线程无法退出condvar.wait(),尽管条件标志设置为TRUE,因为不再有唤醒通知.

可能吗?

c++ condition-variable c++11

6
推荐指数
1
解决办法
5940
查看次数

锁定C++ 11 std :: unique_lock会导致死锁异常

我正在尝试使用C++ 11 std :: condition_variable,但是当我尝试从第二个线程锁定与之关联的unique_lock时,我得到一个异常"资源死锁避免".创建它的线程可以锁定和解锁它,但不能锁定和解锁它,即使我非常确定在第二个线程试图锁定它时不应该锁定unique_lock.

FWIW我在Linux中使用gcc 4.8.1和-std = gnu ++ 11.

我已经在condition_variable,unique_lock和mutex周围写了一个包装类,所以我的代码中没有其他东西可以直接访问它们.注意使用std :: defer_lock,我已经陷入了陷阱:-).

class Cond {
private:
    std::condition_variable cCond;
    std::mutex cMutex;
    std::unique_lock<std::mutex> cULock;
public:
    Cond() : cULock(cMutex, std::defer_lock)
    {}

    void wait()
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Cond %p waiting in thread %s", this, id.str().c_str());
        cCond.wait(cULock);
        H_LOG_D("Cond %p woke up in thread %s", this, id.str().c_str());
    }

    // Returns false on timeout
    bool waitTimeout(unsigned int ms)
    {
        std::ostringstream id;
        id << std::this_thread::get_id();
        H_LOG_D("Cond %p waiting (timed) in thread %s", this, …
Run Code Online (Sandbox Code Playgroud)

linux multithreading mutex condition-variable c++11

6
推荐指数
1
解决办法
1万
查看次数

condition_variable :: wait_for()如何处理虚假的唤醒?

各种平台都允许虚假wakup.为了解决这个问题,我们在下面写出循环机制:

while(ContinueWaiting())
  cv.wait(lock);   // cv is a `std::conditional_variable` object
Run Code Online (Sandbox Code Playgroud)

同样的事情是可以理解的conditional_variable::wait_until().
但请看下面的例子:

const auto duration = Returns_10_seconds();
while(!Predicate())
  cv.wait_for(lock, duration);
Run Code Online (Sandbox Code Playgroud)

想象一下,虚假的唤醒发生在1秒钟.超时尚未达成.
它会再等10秒吗?这将导致无限循环,我相信不应该发生.从源代码,内部wait_for()调用wait_until().

我想了解,如何wait_for()处理虚假的唤醒?

c++ multithreading condition-variable c++11 spurious-wakeup

6
推荐指数
1
解决办法
3836
查看次数

std :: condition_variable :: with谓词等待

在std :: condition_variable的文档中,使用谓词函数作为参数的wait()重载。该函数将一直等到谓词函数为true的第一次wake_up。

文档中

据说这相当于:

while (!pred()) {
    wait(lock);
}
Run Code Online (Sandbox Code Playgroud)

但是也:

在等待特定条件变为真时,可以使用此重载来忽略虚假唤醒。请注意,在进入此方法之前,必须先获取锁,在wait(lock)退出后也必须重新获取它,即锁可以用作pred()访问的保护。

我不确定这些是严格等同的(在这种情况下,我更喜欢普通的while循环,而在我的情况下,这种循环比带有lambda的重载更易于阅读),或者重载(可能取决于实现)更有效?

为了避免测试条件为假时唤醒,实现是否可以在唤醒等待线程之前评估通知线程中的谓词?这里需要c ++线程大师...

谢谢

c++ multithreading std condition-variable c++11

6
推荐指数
2
解决办法
5277
查看次数

可以将std :: condition_variables用作计数信号量吗?

这是Can C++ 11的后续条件condition_variables用于同步进程?.

std :: condition_variable对象可以用作计数信号量吗?

Methinks不是因为对象似乎绑定到std :: mutex,这意味着它只能用作二进制信号量.我在网上看过,包括这里,这里这里,但是找不到使用这些对象作为计数信号量的参考或示例.

c++ multithreading semaphore condition-variable c++11

6
推荐指数
1
解决办法
1131
查看次数

条件变量的这种用法是错误的吗?

C++ Concurrency in Action的第6章,它实现了一个线程安全的队列.是完整的代码.但我发现使用条件变量可能有问题.

  std::unique_lock<std::mutex> wait_for_data()
  {
    std::unique_lock<std::mutex> head_lock(head_mutex);
    data_cond.wait(head_lock, [&] {return head.get() != queue::get_tail(); });
    return std::move(head_lock);
  }

  void push(T new_value)
  {
    std::shared_ptr<T> new_data(
      std::make_shared<T>(std::move(new_value)));
    std::unique_ptr<node> p(new node);
    {
      std::lock_guard<std::mutex> tail_lock(tail_mutex);
      tail->data = new_data;
      node *const new_tail = p.get();
      tail->next = std::move(p);
      tail = new_tail;
    }
    data_cond.notify_one();
  }
Run Code Online (Sandbox Code Playgroud)

消耗部件锁定head_mutex,但生产部件锁定tail_mutex,可能导致消费者错过通知.我好吗?

c++ concurrency multithreading condition-variable

6
推荐指数
0
解决办法
146
查看次数