我有三个工作线程,我希望使用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----|
上面的代码没有这样做,我自己也没能弄明白为什么。非常感谢任何帮助!
答案 0 :(得分:1)
使程序中的线程能够相互通信并同步对共享资源的访问。
同步基元
Special std :: atomic:Mutex保护的标量变量。
不能单独使用,而是使用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