我正在尝试一个示例,它会导致竞争条件应用互斥锁。但是,即使使用互斥锁,它仍然会发生。怎么了?这是我的代码:
#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';
}
答案 0 :(得分:7)
看起来你不是在等待循环中开始的线程完成。将循环更改为:
for (int i = 0; i < 100; ++i)
{
Soldier s;
s.start(30);
s.join();
}
编辑以进一步解释
您看到的问题是打印出的值是错误的,因此您认为线程中存在竞争条件。事实上,比赛是在你打印价值的时候 - 他们被打印出来而并非所有线程都有机会执行
答案 1 :(得分:1)
基于此和您之前的帖子(似乎您还没有阅读所有答案)。您正在寻找的是某种形式的同步点,以防止main()线程退出应用程序(因为当主线程退出应用程序时,所有子线程都会死掉)。
这就是为什么你一直调用join()来阻止main()线程退出,直到线程退出为止。由于您的使用虽然您的线程循环不是并行的,并且每个线程按顺序运行完成(因此使用该线程没有实际意义)。
注意: join()就像在Java中等待线程完成一样。它没有启动线程。
快速查看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();
}
如果我们回到你的例子并改造你的士兵类:
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';
}