先来段代码:
#include <boost/thread.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
void init_number_generator()
{
static boost::thread_specific_ptr<bool> tls;
if (!tls.get())
tls.reset(new bool(false));
if (!*tls)
{
*tls = true;
std::srand(static_cast<unsigned int>(std::time(0)));
}
}
boost::mutex mutex;
void random_number_generator()
{
init_number_generator();
int i = std::rand();
boost::lock_guard<boost::mutex> lock(mutex);
std::cout << i << std::endl;
}
int main()
{
boost::thread t[3];
for (int i = 0; i < 3; ++i)
t[i] = boost::thread(random_number_generator);
for (int i = 0; i < 3; ++i)
t[i].join();
system("pause");
}
运行
后大家可以看到3个完全一样的随机数字,这篇主要说一下TLS变量。
用一个TLS变量 tls 代替静态变量,是基于用 bool
类型实例化的 boost::thread_specific_ptr
。 原则上, tls 工作起来就像静态变量:它可以作为一个条件指明随机数发生器是否被初始化。 但是关键的区别,就是 tls 存储的值只对相应的线程可见和可用。
一旦一个 boost::thread_specific_ptr
型的变量被创建,它可以相应地设置。 不过,它期望得到一个 bool
型变量的地址,而非它本身。使用 reset()
方法,可以把它的地址保存到 tls 里面。 在给出的例子中,会动态地分配一个 bool
型的变量,由 new
返回它的地址,并保存到 tls 里。 为了避免每次调用 init_number_generator()
都设置 tls ,它会通过 get()
函数检查是否已经保存了一个地址。
由于 boost::thread_specific_ptr
保存了一个地址,它的行为就像一个普通的指针。 因此,operator*()
和 operator->()
都被被重载以方便使用。 这个例子用 *tls
检查这个条件当前是 true
还是 false
。 再根据当前的条件,随机数生成器决定是否初始化。
正如所见, boost::thread_specific_ptr
允许为当前进程保存一个对象的地址,然后只允许当前进程获得这个地址。 然而,当一个线程已经成功保存这个地址,其他的线程就会可能就失败。
如果程序正在执行时,它可能会令人感到奇怪:尽管有了TLS的变量,生成的随机数仍然相等。 这是因为,三个线程在同一时间被创建,从而造成随机数生成器在同一时间初始化。 如果该程序执行了几次,随机数就会改变,这就表明生成器初始化正确了。
附上程序截图。
然后我再来一段,由静态变量完成的程序,结果大家自己去分析吧。总给出那么多东西,会让很多看我文章的朋友变得懒惰了。
#include <boost/thread.hpp>
#include <iostream>
#include <cstdlib>
#include <ctime>
void init_number_generator()
{
static bool done = false;
if (!done)
{
done = true;
std::srand(static_cast<unsigned int>(std::time(0)));
}
}
boost::mutex mutex;
void random_number_generator()
{
init_number_generator();
int i = std::rand();
boost::lock_guard<boost::mutex> lock(mutex);
std::cout << i << std::endl;
}
int main()
{
boost::thread t[3];
for (int i = 0; i < 3; ++i)
t[i] = boost::thread(random_number_generator);
for (int i = 0; i < 3; ++i)
t[i].join();
}
好了,今天说了这么多,感觉很对不起大家了。好了结束,给大家自由的去尝试下自己的写代码的感觉吧。