C++ boost thread学习(三)

线程同步

虽然多线程的使用可以提高应用程序的性能,但也增加了复杂性。如果使用线程在同一时间执行几个函数,访问共享资源时必须相应地同步。

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值