#include <boost/thread.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
boost::mutex mutex;
boost::condition_variable_any cond;
std::vector<int> random_numbers;
void fill()
{
std::srand(static_cast<unsigned int>(std::time(0)));
for (int i = 0; i < 3; ++i)
{
boost::unique_lock<boost::mutex> lock(mutex);
random_numbers.push_back(std::rand());
cond.notify_all();
cond.wait(mutex);
}
}
void print()
{
std::size_t next_size = 1;
for (int i = 0; i < 3; ++i)
{
boost::unique_lock<boost::mutex> lock(mutex);
while (random_numbers.size() != next_size)
{
cond.wait(mutex);
}
std::cout << random_numbers.back()<<"---" << std::endl;
++next_size;
cond.notify_all();
}
}
int main()
{
boost::thread t1(fill);
boost::thread t2(print);
t1.join();
t2.join();
}
编译后输出:
703604841---
397897602---
2011646528---
这个例子的程序删除了 wait()
和 count()
。线程不用在每个循环迭代中等待一秒,而是尽可能快地执行。此外,没有计算总额;数字完全写入标准输出流。
为确保正确地处理随机数,需要一个允许检查多个线程之间特定条件的条件变量来同步不每个独立的线程。
正如上面所说, fill()
函数用在每个迭代产生一个随机数,然后放在 random_numbers 容器中。 为了防止其他线程同时访问这个容器,就要相应得使用一个排它锁。 不是等待一秒,实际上这个例子却用了一个条件变量。 调用
notify_all()
会唤醒每个哪些正在分别通过调用wait()
等待此通知的线程。
通过查看 print()
函数里的 for
循环,可以看到相同的条件变量被
wait()
函数调用了。 如果这个线程被 notify_all()
唤醒,它就会试图这个互斥量,但只有在
fill()
函数完全释放之后才能成功。
这里的窍门就是调用 wait()
会释放相应的被参数传入的互斥量。 在调用
后,
notify_all()fill()
函数会通过
相应地释放线程。 然后它会阻止和等待其他的线程调用
wait()notify_all()
,一旦随机数已写入标准输出流,这就会在
print()
里发生。
注意到在 print()
函数里调用 wait()
事实上发生在一个单独
while
循环里。 这样做的目的是为了处理在 print()
函数里第一次调用
wait()
函数之前随机数已经放到容器里。 通过比较 random_numbers 里元素的数目与预期值,发现这成功地处理了把随机数写入到标准输出流。
#include<boost/thread.hpp>
#include<iostream>
using namespace std;
void f1(){
cout<<"f1()"<<endl;
}
void f2(){
cout<<"f2()"<<endl;
}
int main(){
boost::thread_group grp;
for(int i=0;i<3;++i)
{
grp.create_thread(f1);
}
grp.add_thread(new boost::thread(f2));
cout<<grp.size()<<endl;
grp.join_all();
return 1;
}
编译后输出:
4
f1()
f1()
f2()
f1()
这个程序演示了线程组的用法。
Unix C++(boost) 线程同步和线程组