condition_variable和unique_lock如何用于线程安全列表

时间:2017-06-27 10:10:49

标签: c++ multithreading

我正在尝试使用条件变量和唯一锁来创建一个线程安全列表。但是,我遇到了一些问题,似乎列表操作不是线程安全的。

我创建了一个 atomic_flag 来测试它是否是线程安全的。
基本上,当我操作列表时,我将首先检查原子标志是否已设置,并在列表操作完成时清除原子标志。

在我看来,原子标志在互斥保护下运行,因此每当我 test_and_set 原子标志时,我都应该看到初始值应该是假的,但是当我运行测试代码时,我发现它并非如此。

任何人都可以帮助我并指出代码有什么问题,为什么列表操作对于条件变量的保护不是线程安全的?

由于 测试代码如下:

using namespace std;
//list element
class myitem
{
public:
    myitem() { val = -1; };
    myitem(int n, int c){ val = n; chr = c; };
    int val;
    char chr;
};

// mutex and condition variable to protect the list.
std::mutex mymtx;
condition_variable mycv;
    // the list to be protected
    std::list<myitem> mylist;  
    // the atomic flag to test.
    std::atomic_flag testlk = ATOMIC_FLAG_INIT;

void datagenthread(char c)
{
   int n = 10*1000*1000;
   while(n >0)
   {
      myitem item(n, c);
      {
         unique_lock<mutex> lk(mymtx); // get the lock
         if( testlk.test_and_set() != false) { // test the atomic flag
            cout<<"error in thread"<<c<<" for test lock"<<endl; 
         } 
         mylist.push_back(item);
         testlk.clear(); // clear the atomic before unlock.
      }
      mycv.notify_one();
      n--;
   }
}

void datareadthread()
{
   int count = 0;
   int readc = 0;
   while ( count <2)  {
      {
         unique_lock<mutex> lk(mymtx); // acquire lock
         while ( mylist.size() <= 0)   {
            mycv.wait(lk); // block until the thread get notified and get lock again.
         }
         if( testlk.test_and_set()!= false)  {// test the atomic flag.
            cout<<"error in reader thread"<<endl; 
         }
         myitem readitem;
         readitem = mylist.front();
         mylist.pop_front();
         readc++;
         if ( readitem.val == 1)
         {
            cout<<" get last one last item form a thread,"<<endl;
            count++;
         }
         testlk.clear(); // clear the atomic flag before unlock
      }//unique_lock destruct
   }//end while
}
int main()
{
   std::thread cons(   datareadthread);
   std::thread gen1(   datagenthread, 'a');
   std::thread gen2(   datagenthread, 'b');
   gen1.join();
   gen2.join();
   cons.join();
   return 0;
}

2 个答案:

答案 0 :(得分:0)

testlk默认构造函数将其初始化为未指定的状态,因此在第一次迭代时,初始值为false以外的值。你应该用清除状态初始化它,如下所示:

std::atomic_flag testlk = ATOMIC_FLAG_INIT;

答案 1 :(得分:0)

我找到了原因,似乎我链接了一些错误的libs导致mutex / condition_var无法正常工作。