简体   繁体   English

仍然有 boost::mutex 的竞争条件

[英]Still having race condition with boost::mutex

I am trying an example, which causes race condition to apply the mutex.我正在尝试一个示例,它会导致竞争条件应用互斥锁。 However, even with the mutex, it still happens.但是,即使使用互斥体,它仍然会发生。 What's wrong?怎么了? Here is my code:这是我的代码:

#include <iostream>
#include <boost/thread.hpp>
#include <vector>
using namespace std;
class Soldier
{
private:
  boost::thread m_Thread;
public:
  static int count , moneySpent;
  static boost::mutex soldierMutex;   
  Soldier(){}
  void start(int cost)
  {
    m_Thread = boost::thread(&Soldier::process, this,cost);
  }

  void process(int cost)
  {
    {
    boost::mutex::scoped_lock lock(soldierMutex);
    //soldierMutex.lock();
    int tmp = count;
    ++tmp;
    count = tmp;
    tmp = moneySpent;
    tmp += cost;
    moneySpent = tmp;  
   // soldierMutex.unlock();
    }
  }  

  void join()
  {
    m_Thread.join();
  }
};

int Soldier::count, Soldier::moneySpent;
boost::mutex Soldier::soldierMutex;

int main()
{
  Soldier s1,s2,s3;
  s1.start(20);
  s2.start(30);
  s3.start(40);
  s1.join();
  s2.join();
  s3.join();
  for (int i = 0; i < 100; ++i)
    {
      Soldier s;
      s.start(30);
    }
  cout << "Total soldier: " << Soldier::count << '\n';
  cout << "Money spent: " << Soldier::moneySpent << '\n';
}

It looks like you're not waiting for the threads started in the loop to finish.看起来您并没有等待循环中启动的线程完成。 Change the loop to:将循环更改为:

 for (int i = 0; i < 100; ++i)
 {
   Soldier s;
   s.start(30);
   s.join();
 }

edit to explain further编辑以进一步解释

The problem you saw was that the values printed out were wrong, so you assumed there was a race condition in the threads.您看到的问题是打印出来的值是错误的,因此您假设线程中存在竞争条件。 The race in fact was when you printed the values - they were printed while not all the threads had a chance to execute事实上,比赛是在您打印值时 - 它们被打印,而并非所有线程都有机会执行

Based on this and your previous post (were it does not seem you have read all the answers yet).基于此和您之前的帖子(如果您似乎还没有阅读所有答案)。 What you are looking for is some form of synchronization point to prevent the main() thread from exiting the application (because when the main thread exits the application all the children thread die).您正在寻找的是某种形式的同步点,以防止 main() 线程退出应用程序(因为当主线程退出应用程序时,所有子线程都会死掉)。

This is why you call join() all the time to prevent the main() thread from exiting until the thread has exited.这就是为什么您一直调用 join() 以防止 main() 线程退出,直到线程退出。 As a result of your usage though your loop of threads is not parallel and each thread is run in sequence to completion (so no real point in using the thread).由于您的使用,尽管您的线程循环不是并行的,并且每个线程都按顺序运行直到完成(因此使用线程没有真正意义)。

Note: join() like in Java waits for the thread to complete.注意:像 Java 中的 join() 等待线程完成。 It does not start the thread.它不会启动线程。

A quick look at the boost documentation suggests what you are looking for is a thread group which will allow you to wait for all threads in the group to complete before exiting.快速查看 boost 文档表明您正在寻找的是一个线程组,它允许您在退出之前等待组中的所有线程完成。

//No compiler so this is untested.
// But it should look something like this.
// Note 2: I have not used boost::threads much.
int main()
{
    boost::thread_group               group;

    boost::ptr_vector<boost::thread>  threads;

    for(int loop = 0; loop < 100; ++loop)
    {
        // Create an object.
        // With the function to make it start. Store the thread in a vector
        threads.push_back(new boost::thread(<Function To Call>));

        // Add the thread to the group.
        group.add(threads.back());
    }

    // Make sure main does not exit before all the threads have completed.
    group.join_all();
}

If we go back to your example and retrofit your Soldier class:如果我们 go 回到你的例子, retrofit 你的士兵 class:

int main()
{
  boost::thread batallion;

  // Make all the soldiers part of a group.
  // When you start the thread make the thread join the group.
  Soldier s1(batallion);
  Soldier s2(batallion);
  Soldier s3(batallion);

  s1.start(20);
  s2.start(30);
  s3.start(40);

  // Create 100 soldiers outside the loo
  std::vector<Soldier>  lotsOfSoldiers;
  lotsOfSoldiers.reserve(100);  // to prevent reallocation in the loop.
                                // Because you are using objects we need to 
                                // prevent copying of them after the thread starts.

  for (int i = 0; i < 100; ++i)
  {
      lotsOfSoldiers.push_back(Solder(batallion));
      lotsOfSoldiers.back().start(30);
  }

  // Print out values while threads are still running
  // Note you may get here before any thread.
  cout << "Total soldier: " << Soldier::count << '\n';
  cout << "Money spent: " << Soldier::moneySpent << '\n';

  batallion.join_all();

  // Print out values when all threads are finished.
  cout << "Total soldier: " << Soldier::count << '\n';
  cout << "Money spent: " << Soldier::moneySpent << '\n';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM