线程同步
虽然多线程的使用可以提高应用程序的性能,但也增加了复杂性。如果使用线程在同一时间执行几个函数,访问共享资源时必须相应地同步。
Boost.Thread提供多个的互斥类。
boost::mutex是最简单的一个,它的使用就像linux下的二进制互斥量。互斥的基本原则是当一个特定的线程拥有资源的时候防止其他线程夺取其所有权,一旦释放,其他的线程可以取得所有权。这将导致线程等待至另一个线程完成处理一些操作,从而相应地释放互斥对象的所有权。
下面的示例使用一个类型为 boost::mutex 的simple_mutex全局互斥对象。thread()函数获取此对象的所有权才在 for 循环内使用 lock()方法写入到标准输出流的。一旦信息被写入,使用unlock()方法释放所有权。
testSimpleMutex() 创建两个线程,同时执行thread ()函数。利用 for 循环,每个线程数到5,用一个迭代器写一条消息到标准输出流。然而,标准输出流是一个全局性的被所有线程共享的对象,该标准不提供任何保证 std::cout 可以安全地从多个线程访问。 因此,访问标准输出流必须同步:在任何时候,只有一个线程可以访问 std::cout。
由于两个线程试图在写入标准输出流前获得互斥体,实际上只能保证一次只有一个线程访问 std::cout。不管哪个线程成功调用 lock() 方法,其他所有线程必须等待,直到 unlock() 被调用。
mutex例子:
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
boost::mutex simple_mutex;
using namespace std;
void wait(int seconds)
{
boost::this_thread::sleep(boost::posix_time::seconds(seconds));
}
void simpleMutex()
{
for (int i = 0; i < 5; i++)
{
wait(1);
simple_mutex.lock();
cout << "Thread" << boost::this_thread::get_id() << " : " << i << endl;
simple_mutex.unlock();
}
}
void testSimpleMutex()
{
boost::thread t1(simpleMutex);
boost::thread t2(simpleMutex);
t1.join();
t2.join();
}
int main(int argc, char* argv[])
{
testSimpleMutex();
return 0;
}
boost::lock_guard,在其内部构造和析构函数分别自动调用lock() 和 unlock() 。 实现获取和释放互斥体的功能。
如下例:
void thread()
{
for (int i = 0; i < 5; ++i)
{
wait(1);
boost::lock_guard lock(simple_mutex);
std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl;
}
}
boost::unique_lock,典型用法,boost::unique_lock lock(mutex, boost::try_to_lock);第二个参数传入一个 boost::try_to_lock 类型的值,对应的构造函数就会调用 try_lock方法。这个方法返回 bool 型的值:如果能够获得互斥体则返回true,否则返回 false。相比lock函数,try_lock会立即返回,而且在获得互斥体之前不会被阻塞。
如下例:
boost::timed_mutex time_mutex;
void uniqueLockThread()
{
for (int i = 0; i < 5; ++i)
{
wait(1);
boost::unique_lock<boost::timed_mutex> lock(time_mutex, boost::try_to_lock);
if (!lock.owns_lock())
{
lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(1));
}
time_mutex.unlock();
std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << endl;
}
}
void testUniqueLockThread()
{
boost::thread t1(uniqueLockThread);
boost::thread t2(uniqueLockThread);
t1.join();
t2.join();
}
上面的程序向boost::unique_lock 的构造函数的第二个参数传入boost::try_to_lock。然后通过 owns_lock() 可以检查是否可获得互斥体。如果不能, owns_lock() 返回false。这也用到 boost::unique_lock 提供的另外一个函数: timed_lock() 等待一定的时间以获得互斥体。 给定的程序等待长达1秒,应较足够的时间来获取更多的互斥。
三个方法获取一个互斥体:
lock() 会一直等待,直到获得一个互斥体。
try_lock()则不会等待,但如果它只会在互斥体可用的时候才能获得,否则返回 false。
timed_lock()试图获得在一定的时间内获取互斥体。和try_lock()一样,返回bool 类型的值意味着成功是否。
boost::unique_lock 这个所谓的独占锁意味着一个互斥量同时只能被一个线程获取。其他线程必须等待,直到互斥体再次被释放。
非独占锁。 boost::shared_lock 的类提供了非独占锁,这个类必须和 boost::shared_mutex 型的互斥量一起使用。boost::shared_mutex它允许线程获取多个共享所有权和一个专享所有权,它比mutex的代价高很多。通过lock_shared()或try_lock_shared()获取共享所有权,使用unlock_shared()来释放共享所有权。
读锁定时shared_lock<shared_mutex>,写锁定时使用unique_lock<shared_mutex>。
如下例
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
class rw_data
{
private:
int m_x;
boost::shared_mutex rw_mu;
public:
rw_data():m_x(0){}
void write()
{
boost::unique_lock<boost::shared_mutex> ul(rw_mu);
++m_x;
}
void read(int *x)
{
boost::shared_lock<boost::shared_mutex> sl(rw_mu);
*x = m_x;
}
};
void writer(rw_data &d)
{
for (int i = 0; i < 20; ++i)
{
boost::this_thread::sleep(boost::posix_time::seconds(10));
d.write();
cout << "writer:" << i << endl;
}
}
void reader(rw_data &d)
{
int x;
for (int i = 0; i < 10; ++i)
{
boost::this_thread::sleep(boost::posix_time::seconds(5));
d.read(&x);
cout << "reader:" << x << endl;
}
}
void testSharedMutex()
{
rw_data d;
boost::thread_group pool;
pool.create_thread(boost::bind(reader, boost::ref(d)));
pool.create_thread(boost::bind(reader, boost::ref(d)));
pool.create_thread(boost::bind(reader, boost::ref(d)));
pool.create_thread(boost::bind(reader, boost::ref(d)));
pool.create_thread(boost::bind(writer, boost::ref(d)));
pool.create_thread(boost::bind(writer, boost::ref(d)));
pool.join_all();
}
int main(int argc, char* argv[])
{
testSharedMutex();
return 0;
}
分享到:
相关推荐
C++ Boost Thread 编程指南 0分上船
C++ Boost Thread 编程指南.doc
最近开发中用到大量BOOST库的东西,现在把我开发中总结的boost使用方法分享一下,里面包括智能指针、boost定时器、boostthread和io_service等的用法和说明,还有一本Beyond the C++ Standard Library: An ...
标准C++线程即将到来。CUJ预言它将衍生自Boost线程库,现在就由Bill带领我们探索一下Boost线程库。 就在几年前,用多线程执行程序还是一件非比寻常的事。然而今天互联网应用服务程序普遍使用多线程来提高与多客户...
首先看看boost::thread的构造函数吧,boost::thread有两个构造函数: (1)thread():构造一个表示当前执行线程的线程对象; (2)explicit thread(const boost::function0& threadfunc): boost::function0可以...
C++_Boost_Thread_编程指南
Boost库是一个经过千锤百炼、可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的发动机之...Thread 可移植的C++多线程库;Python 把C++类和函数映射到Python之中;Pool 内存池管理;smart_ptr 智能指针。
很好用的boost线程池,实际例子在test目录
THE BOOST C++ LIBRARIES是一份自己编译的chm格式文档,描述了如何使用boost类库,目录如下: Front page Chapter 1: Introduction 1.1 C++ and Boost 1.2 Development Process 1.3 Installation 1.4 Overview ...
C++ boost::asio编程-域名解析 在网络通信中通常我们并不直接使用IP地址,而是使用域名。这时候我们就需要用reslover类来通过域名获取IP,它可以实现 与IP版本无关的网址解析。 #include stdafx.h #include boost/...
boost.thread.1.3.5中文翻译
boost-thread.pdf boost_1_41_文档_中文版.chm boost_1_43_0_doc_en.chm Boost库学习指南.pdf Boost教程.pdf boost概览.pdf 侯捷_-_Boost_技术与应用.pdf 智能指针的标准之争 Boost_vs_Loki.pdf
Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一。 Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是...
Boost库文件采用的.hpp的后缀,而不是分成两个文件,也就是”.h+.cpp”,之所以这样做是有理由的,首先就是与普通的C/...Boost中90%的库不需要编译,但像data_time、regex、test、thread等库必须编译成静态库或者动态库
Boost库是一个经过千锤百炼、可移植、提供源代码的C++库,,作为标准库的后备,是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响...
signal 库,还有泛型编程、模板编程子库如 call traits、mpl,还有并发编程相关的 thread 库,等等等等。 Boost 是如此强大,毫无疑问它也很大。Windows 上安装 boost 需要占用 2G+ 的空间,编译配置起来也
boost.thread.pdf、Boost_Thread_编程指南.pdf、Boost程序库完全开发指南_深入C++准标准库.pdf、侯捷_-_Boost_技术与应用.pdf等资料,需要Boost编程资料的可以下载。
对于C++而言,当我们需要使用多线程时,可以使用boost::thread库或者自从C++ 11开始支持的std::thread,也可以使用操作系统相关的线程API,如在Linux上,可以使用pthread库。除此之外,还可以使用omp来使用多线程。...