【发布时间】:2013-08-01 03:01:27
【问题描述】:
这是 Anthony Williams 在第 6.2.3 章 C++ Concurrency in Action 中介绍的细粒度锁定队列。
/*
pop only need lock head_mutex and a small section of tail_mutex,push only need
tail_mutex mutex.maximum container concurrency.
*/
template<typename T> class threadsafe_queue
{
private:
struct node
{
std::shared_ptr<T> data;
std::unique_ptr<node> next;
}
std::mutex head_mutex; //when change the head lock it.
std::unique_ptr<node> head;
std::mutex tail_mutex; //when change the tail lock it.
node* tail;
std::condition_variable data_cond;
node* get_tail()
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
return tail;
}
public:
/*
create a dummy node
*/
threadsafe_queue():
head(new node),tail(head.get())
{}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> head_lock;
data_cond.wait(head_lock,[&]{return head.get()!=get_tail();}); //#1
std::unique_ptr<node> old_head=std::move(head);
head=std::move(old_head->next);
return old_head;
}
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();
}
}
情况如下:有两个线程(thread1 和thread2)。 thread1 正在执行 wait_and_pop 和 thread2 正在执行 push。队列为空。
thread1 在#2 中,在data_cond.wait() 之前已经检查过head.get()!=get_tail()。此时它的 CPU 周期已经用完。 thread2 开始。
thread2 完成了push 函数并执行了data_cond.notify_one()。 thread1 又开始了。
现在thread1 开始于data_cond.wait(),但它一直在等待。
这种情况会不会发生?如果会,如何修复这个容器?
【问题讨论】:
标签: c++ multithreading concurrency stl