带条件变量的C ++ 11多线程

时间:2014-09-07 05:50:22

标签: multithreading c++11

我有三个工作线程,我希望使用C ++ 11中的条件变量从main()进行协调。下面的代码说明了我的方法:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

const int T_COUNT = 3;
thread* Threads[T_COUNT];
condition_variable cv[T_COUNT];
mutex m[T_COUNT];
bool Ready[T_COUNT] = {0};
bool Running[T_COUNT] = {0};

void worker(int tid) {
    while (1) {
        unique_lock<mutex> lk(m[tid]);
        cv[tid].wait(lk, [&]{return Ready[tid];});

        cout << "Processing thread #" << tid << endl;

        Ready[tid] = false;
        lk.unlock();
        cv[tid].notify_all();
    }
}

int main() {
    int tid = 0;
    while (1) {
        if (Running[tid]) {
            unique_lock<mutex> lk(m[tid]);
            cv[tid].wait(lk, [&]{return !Ready[tid];});
            Ready[tid] = true;
            lk.unlock();
            cv[tid].notify_all();
        } else {
            cout << "Creating thread #" << tid << endl;
            Threads[tid] = new thread([&]{
                worker(tid);
            });
            Running[tid] = true;
            cv[tid].notify_all();
        }
        tid = (tid + 1) % T_COUNT;
    }
}

我希望此代码生成如下输出:

...
Processing thread #0
Processing thread #1
Processing thread #2
Processing thread #0
Processing thread #1
Processing thread #2
...

线程循环完成迭代并不重要,每个线程迭代与其他线程按顺序开始也很重要。为了直观地说明我的目标:

|----T0----|
 |----T1----|
     |----T2----|
            |----T0----|
               |----T1----|
                 |----T2----|

上面的代码没有这样做,我自己也没能弄明白为什么。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

线程同步机制

使程序中的线程能够相互通信并同步对共享资源的访问。

同步基元

  • Mutex(C ++ 11)

Special std :: atomic:Mutex保护的标量变量。

  • 信号量
  • 条件变量(C ++ 11)

不能单独使用,而是使用std :: mutex。

  • 事件标志(标志中的每个位代表一个条件)
  • 留言箱(邮箱)

注意:可以使用互斥锁和条件变量实现信号量和邮箱。

信号量 - 解决生产者/消费者问题

信号量包含一个指示资源是否已锁定或可用的计数。信号量是信号机制(“我做完了,你可以继续。”)。资源本身可能不是线程安全的。

<强>生产者

semObject.Post();   // Send the signal
  

将信号量计数增加1.如果线程正在等待   指定的信号量,它被唤醒。[1]

<强>消费

semObject.Wait();   // Wait for the signal
  

当信号量计数为零时,调用此函数的线程   将等待信号量。当信号量计数非零时,   count将减1并且线程调用此函数   将继续。[1]

信号量可以使用互斥锁和条件变量

来实现
void Semaphore::Post()
{
    {
        lock_guard<mutex> lockGuard(m_mtx);
        ++m_count;
    }   // release lock
    m_cv.notify_one();  // Since the count increments only 1, notifying one is enough. This call does not need to be locked.
}

void Semaphore::Wait(const bool resetCount /*= false*/)
{
    unique_lock<mutex> mtxLock(m_mtx);      // Must use unique_lock with condition variable.
    m_cv.wait(mtxLock, [this]{ return m_count > 0; });      // Blocking till count is not zero.
    if (resetCount)
    {
        m_count = 0;    // Reset the signal.
    }
    else
    {
        --m_count;      // Normal wait.
    }
}

使用信号量来解决您的问题

#include "Semaphore.h"

using namespace std;

const int T_COUNT = 3;
static Semaphore sem[T_COUNT];

void Worker(int tid) 
{
    for (;;)
    {
        sem[tid].Wait();    // Wait for signal, blocking.
        cout << "Processing thread #" << tid << endl;
        sem[(tid + 1) % T_COUNT].Post();    // Inform next worker to run.
        this_thread::sleep_for(chrono::seconds(tid + 1));   // Actual timing consuming work.
    }
}

int main()
{
    // Create all threads first.
    thread th[T_COUNT];
    for (int i = 0; i < T_COUNT; ++i)
    {
        th[i] = thread(Worker, i);
    }

    // Start to run by signaling the first worker.
    sem[0].Post();

    // End of work.
    for (int i = 0; i < T_COUNT; ++i)
    {
        th[i].join();
    }
}

参考

[1] Massa,Anthony J.,eCos嵌入式软件开发,Pearson Education,Inc.,2002