boost库中thread多线程详解

831 篇文章 16 订阅
300 篇文章 0 订阅

1. 概述

线程就是,在同一程序同一时间内允许执行不同函数的离散处理队列。 这使得一个长时间去进行某种特殊运算的函数在执行时不阻碍其他的函数变得十分重要。 线程实际上允许同时执行两种函数,而这两个函数不必相互等待。

一旦一个应用程序启动,它仅包含一个默认线程。 此线程执行main() 函数。 在main()中被调用的函数则按这个线程的上下文顺序地执行。 这样的程序称为单线程程序。

反之,那些创建新的线程的程序就是多线程程序。 他们不仅可以在同一时间执行多个函数,而且这在如今多核盛行的时代显得尤为重要。 既然多核允许同时执行多个函数,这就使得对开发人员相应地使用这种处理能力提出了要求。 然而线程一直被用来当并发地执行多个函数,开发人员现在不得不仔细地构建应用来支持这种并发。 多线程编程知识也因此在多核系统时代变得越来越重要。

2. 线程管理

2.1 情景1(test_thread_wait1)

在这个库最重要的一个类就是boost::thread,它是在boost/thread.hpp里定义的,用来创建一个新线程。下面的示例来说明如何运用它。

新建线程里执行的那个函数的名称被传递到boost::thread的构造函数。 一旦上述示例中的变量t 被创建,该 thread() 函数就在其所在线程中被立即执行。 同时在test_thread_wait1()里也并发地执行该 threadfun1() 。

为了防止程序终止,就需要对新建线程调用join() 方法。join() 方法是一个阻塞调用:它可以暂停当前线程,直到调用 join() 的线程运行结束。这就使得test_thread_wait1()函数一直会等待到 threadfun1()运行结束。

正如在上面的例子中看到,一个特定的线程可以通过诸如t的变量访问,通过这个变量等待着它的使用 join() 方法终止。 但是,即使 t 越界或者析构了,该线程也将继续执行。 一个线程总是在一开始就绑定到一个类型为 boost::thread 的变量,但是一旦创建,就不在取决于它。 甚至还存在着一个叫detach()的方法,允许类型为boost::thread 的变量从它对应的线程里分离。 当然了,像join()的方法之后也就不能被调用,因为这个变量不再是一个有效的线程。

任何一个函数内可以做的事情也可以在一个线程内完成。 归根结底,一个线程只不过是一个函数,除了它是同时执行的。 在上述例子中,使用一个循环把5个数字写入标准输出流。 为了减缓输出,每一个循环中调用wait() 函数让执行延迟了一秒。 wait() 可以调用一个名为sleep() 的函数,这个函数也来自于 Boost.Thread,位于 boost::this_thread 名空间内。

sleep() 要么在预计的一段时间或一个特定的时间点后时才让线程继续执行。 通过传递一个类型为boost::posix_time::seconds 的对象,在这个例子里我们指定了一段时间。 boost::posix_time::seconds 来自于Boost.DateTime库,它被 Boost.Thread 用来管理和处理时间的数据。

虽然前面的例子说明了如何等待一个不同的线程,但下面的例子演示了如何通过所谓的中断点让一个线程中断。

2.2 情景2(test_thread_wait2())

在一个线程对象上调用 interrupt() 会中断相应的线程。在这方面,中断意味着一个类型为boost::thread_interrupted的异常,它会在这个线程中抛出。然后这只有在线程达到中断点时才会发生。

如果给定的线程不包含任何中断点,简单调用interrupt() 就不会起作用。每当一个线程中断点,它就会检查interrupt() 是否被调用过。只有被调用过了, boost::thread_interrupted 异常才会相应地抛出。

Boost.Thread定义了一系列的中断点,例如sleep()函数。由于sleep()在这个例子里被调用了五次,该线程就检查了五次它是否应该被中断。然而sleep()之间的调用,却不能使线程中断。

一旦该程序被执行,它只会打印三个数字到标准输出流。这是由于在test_thread_wait2()里3秒后调用 interrupt()方法。因此,相应的线程被中断,并抛出一个boost::thread_interrupted 异常。 这个异常在线程内也被正确地捕获,catch处理虽然是空的。由于thread() 函数在处理程序后返回,线程也被终止。这反过来也将终止整个程序,因为test_thread_wait2()等待该线程使用join()终止该线程。

Boost.Thread定义包括上述 sleep()函数十个中断。有了这些中断点,线程可以很容易及时中断。然而,他们并不总是最佳的选择,因为中断点必须事前读入以检查boost::thread_interrupted异常。

3.示例

  1. void wait(int seconds)  
  2. {  
  3.     boost::this_thread::sleep(boost::posix_time::seconds(seconds));  
  4. }  
  5.   
  6. void threadfun1()  
  7. {  
  8.     for (int i = 0; i < 5; ++i)  
  9.     {  
  10.         wait(1);  
  11.         PRINT_DEBUG(i);  
  12.     }  
  13. }  
  14.   
  15. void threadfun2()   
  16. {  
  17.     try  
  18.     {  
  19.         for (int i = 0; i < 5; ++i)  
  20.         {  
  21.             wait(1);  
  22.             PRINT_DEBUG(i);  
  23.         }  
  24.     }  
  25.     catch (boost::thread_interrupted&)  
  26.     {  
  27.         PRINT_DEBUG("thread_interrupted");  
  28.     }  
  29. }  
  30.   
  31. void test_thread_wait1()  
  32. {  
  33.     boost::thread t(&threadfun1);  
  34.     // join()方法是一个阻塞调用:它可以暂停当前线程,直到调用join()的线程运行结束。   
  35.     t.join();  
  36. }  
  37.   
  38. void test_thread_wait2()  
  39. {  
  40.     boost::thread t(&threadfun2);  
  41.     wait(3);  
  42.     t.interrupt();  
  43.     t.join();  
  44. }  
  45.   
  46. void test_thread_wait3()  
  47. {  
  48.     boost::thread t(&threadfun2);  
  49.     // timed_join()方法同样也是一个阻塞调用:它可以暂停当前线程,   
  50.     // 直到调用join()的线程运行结束或者超时   
  51.     t.timed_join(boost::posix_time::seconds(3));  
  52. }  
  53.   
  54. void test_thread_wait4()  
  55. {  
  56.     boost::thread t(&threadfun2);  
  57.     wait(3);  
  58.     // 当thread 与线程执行体分离时,线程执行体将不受影响地继续执行,   
  59.     // 直到运行结束,或者随主线程一起结束。   
  60.     t.detach();  
  61.     // 此时join无作用   
  62.     t.join();  
  63.     // t不再标识任何线程 {Not-any-thread}   
  64.     assert(t.get_id() == boost::thread::id());  
  65. }  
void wait(int seconds)
{
	boost::this_thread::sleep(boost::posix_time::seconds(seconds));
}

void threadfun1()
{
	for (int i = 0; i < 5; ++i)
	{
		wait(1);
		PRINT_DEBUG(i);
	}
}

void threadfun2() 
{
	try
	{
		for (int i = 0; i < 5; ++i)
		{
			wait(1);
			PRINT_DEBUG(i);
		}
	}
	catch (boost::thread_interrupted&)
	{
		PRINT_DEBUG("thread_interrupted");
	}
}

void test_thread_wait1()
{
	boost::thread t(&threadfun1);
	// join()方法是一个阻塞调用:它可以暂停当前线程,直到调用join()的线程运行结束。
	t.join();
}

void test_thread_wait2()
{
	boost::thread t(&threadfun2);
	wait(3);
	t.interrupt();
	t.join();
}

void test_thread_wait3()
{
    boost::thread t(&threadfun2);
    // timed_join()方法同样也是一个阻塞调用:它可以暂停当前线程,
    // 直到调用join()的线程运行结束或者超时
    t.timed_join(boost::posix_time::seconds(3));
}

void test_thread_wait4()
{
    boost::thread t(&threadfun2);
    wait(3);
    // 当thread 与线程执行体分离时,线程执行体将不受影响地继续执行,
    // 直到运行结束,或者随主线程一起结束。
    t.detach();
    // 此时join无作用
    t.join();
    // t不再标识任何线程 {Not-any-thread}
    assert(t.get_id() == boost::thread::id());
}



 

1. mutex对象类

mutex类主要有两种:独占式与共享式的互斥量。
▲ 独占式互斥量:
mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型
try_mutex: 它是mutex的同义词,为了与兼容以前的版本而提供
timed_mutex: 它也是独占式的互斥量,但提供超时锁定功能
▲ 递归式互斥量:
recursive_mutex: 递归式互斥量,可以多次锁定,相应地也要多次解锁
recursive_try_mutex: 它是recursive_mutex 的同义词,为了与兼容以前的版本而提供
recursive_timed_mutex: 它也是递归式互斥量,基本功能同recursive_mutex, 但提供超时锁定功能
▲ 共享式互斥量:
shared_mutex: multiple-reader/single-writer 型的共享互斥量(又称读写锁)。
其中mutex有lock和unlock方法,shared_mutex除了提供lock和unlock方法外,还有shared_lock和shared_unlock方法。

2. lock模板类

▲ 独占锁:
boost::unique_lock<T>,其中T可以mutex中的任意一种。
  如果T为mutex,那么boost::unique_lock<boost::mutex>,构造与析构时则分别自动调用lock和unlock方法。
  如果T为shared_mutex,那么boost::unique_lock<boost::shared_mutex>,构造与析构时则分别调用shared_mutex的shared_lock和shared_unlock方法。
注意:scoped_lock也是独占锁,其源代码中定义如下;
  typedef unique_lock<mutex> scoped_lock;
  typedef unique_lock<timed_mutex> scoped_timed_lock;
▲ 共享锁:
boost::shared_lock<T>,其中的T只能是shared_mutex类。
当然还有其他一些锁:lock_guard, upgrade_lock等。

3. 读写锁的实现

  1. typedef boost::shared_lock<boost::shared_mutex> readLock;  
  2. typedef boost::unique_lock<boost::shared_mutex> writeLock;  
  3. boost::shared_mutex rwmutex;  
  4.   
  5. void readOnly()  
  6. {  
  7.   readLock rdlock(rwmutex);  
  8.   // do something   
  9. }  
  10.   
  11. void writeOnly()  
  12. {  
  13.   writeLock wtlock(rwmutex);  
  14.   // do something   
  15. }  
typedef boost::shared_lock<boost::shared_mutex> readLock;
typedef boost::unique_lock<boost::shared_mutex> writeLock;
boost::shared_mutex rwmutex;

void readOnly()
{
  readLock rdlock(rwmutex);
  // do something
}

void writeOnly()
{
  writeLock wtlock(rwmutex);
  // do something
}

对同一个rwmutex,线程可以同时有多个readLock,这些readLock会阻塞任意一个企图获得writeLock的线程,直到所有的readLock对象都析构。如果writeLock首先获得了rwmutex,那么它会阻塞任意一个企图在rwmutex上获得readLock或者writeLock的线程。

4. boost::lock_guard<>和boost::unique_lock<>的区别

  1. boost::mutex m;  
  2. void foo( )  
  3. {  
  4.   boost::lock_guard<boost::mutex> lk(m);  
  5.   process(data);  
  6. };  
  7.   
  8. // lock_guard只能像上面这样使用,而unique_lock允许设置超时,推迟锁定lock以及在对象销毁之前unlock。   
  9. {  
  10.   boost::unique_lock<boost::mutex> lk( m );  
  11.   process( data );  
  12.   lk.unlock( );  
  13.   // do other thing   
  14. };  
  15.   
  16. // 设置锁超时   
  17. {  
  18.   boost::unique_lock<boost::timed_mutex> lk(m, std::chrono::milliseconds(3)); // 超时3秒   
  19.   if(lk)  
  20.     process( data );  
  21. };  
boost::mutex m;
void foo( )
{
  boost::lock_guard<boost::mutex> lk(m);
  process(data);
};

// lock_guard只能像上面这样使用,而unique_lock允许设置超时,推迟锁定lock以及在对象销毁之前unlock。
{
  boost::unique_lock<boost::mutex> lk( m );
  process( data );
  lk.unlock( );
  // do other thing
};

// 设置锁超时
{
  boost::unique_lock<boost::timed_mutex> lk(m, std::chrono::milliseconds(3)); // 超时3秒
  if(lk)
    process( data );
};

5. 简单示例

  1. namespace  
  2. {  
  3.     boost::mutex mutex;  
  4.     boost::shared_mutex shared_mutex;  
  5.   
  6.     void wait(int seconds)  
  7.     {  
  8.         boost::this_thread::sleep(boost::posix_time::seconds(seconds));  
  9.     }  
  10.   
  11.     void threadfun1()  
  12.     {  
  13.         for (int i = 0; i < 5; ++i)  
  14.         {  
  15.             wait(1);  
  16.             mutex.lock();  
  17.             PRINT_DEBUG(i);  
  18.             mutex.unlock();  
  19.         }  
  20.     }  
  21.   
  22.     void threadfun2()  
  23.     {  
  24.         for (int i = 0; i < 5; ++i)  
  25.         {  
  26.             wait(1);  
  27.             boost::lock_guard<boost::mutex> lock(mutex);  
  28.             PRINT_DEBUG(i);  
  29.         }  
  30.     }  
  31.       
  32.     void threadfun3()  
  33.     {  
  34.         for (int i = 0; i < 5; ++i)  
  35.         {  
  36.             wait(1);  
  37.             // unique_lock<boost::mutex> = scoped_lock   
  38.             boost::unique_lock<boost::mutex> lock(mutex);  
  39.             std::cout << lock.owns_lock() << std::endl;  
  40.             PRINT_DEBUG(i);  
  41.         }  
  42.     }  
  43. }  
  44.   
  45. // 1. mutex例子   
  46. void test_thread_syn1()  
  47. {  
  48.     boost::thread t1(&threadfun1);  
  49.     boost::thread t2(&threadfun1);  
  50.   
  51.     t1.join();  
  52.     t2.join();  
  53. }  
  54.   
  55. //  2. lock_guard例子   
  56. void test_thread_syn2()  
  57. {  
  58.     boost::thread t1(&threadfun2);  
  59.     boost::thread t2(&threadfun2);  
  60.   
  61.     t1.join();  
  62.     t2.join();  
  63. }  
  64.   
  65. // 3. scoped_lock例子   
  66. void test_thread_syn3()  
  67. {  
  68.     boost::thread t1(&threadfun3);  
  69.     boost::thread t2(&threadfun3);  
  70.   
  71.     t1.join();  
  72.     t2.join();  
  73. }  
namespace
{
	boost::mutex mutex;
	boost::shared_mutex shared_mutex;

	void wait(int seconds)
	{
		boost::this_thread::sleep(boost::posix_time::seconds(seconds));
	}

	void threadfun1()
	{
		for (int i = 0; i < 5; ++i)
		{
			wait(1);
			mutex.lock();
			PRINT_DEBUG(i);
			mutex.unlock();
		}
	}

	void threadfun2()
	{
		for (int i = 0; i < 5; ++i)
		{
			wait(1);
			boost::lock_guard<boost::mutex> lock(mutex);
			PRINT_DEBUG(i);
		}
	}
	
	void threadfun3()
	{
		for (int i = 0; i < 5; ++i)
		{
			wait(1);
			// unique_lock<boost::mutex> = scoped_lock
			boost::unique_lock<boost::mutex> lock(mutex);
			std::cout << lock.owns_lock() << std::endl;
			PRINT_DEBUG(i);
		}
	}
}

// 1. mutex例子
void test_thread_syn1()
{
	boost::thread t1(&threadfun1);
	boost::thread t2(&threadfun1);

	t1.join();
	t2.join();
}

// 	2. lock_guard例子
void test_thread_syn2()
{
	boost::thread t1(&threadfun2);
	boost::thread t2(&threadfun2);

	t1.join();
	t2.join();
}

// 3. scoped_lock例子
void test_thread_syn3()
{
	boost::thread t1(&threadfun3);
	boost::thread t2(&threadfun3);

	t1.join();
	t2.join();
}


 

boost::lock_guard可以说是一种比boost::unique_lock轻量级的lock, 简单一些场景可以用它就行了。
看看它的源代码也很简单:
  1. template<typename Mutex>  
  2. class lock_guard  
  3. {  
  4. private:  
  5.     Mutex& m;  
  6.   
  7.     explicit lock_guard(lock_guard&);  
  8.     lock_guard& operator=(lock_guard&);  
  9. public:  
  10.     explicit lock_guard(Mutex& m_):  
  11.         m(m_)  
  12.     {  
  13.         m.lock();  
  14.     }  
  15.     lock_guard(Mutex& m_,adopt_lock_t):  
  16.         m(m_)  
  17.     {}  
  18.     ~lock_guard()  
  19.     {  
  20.         m.unlock();  
  21.     }  
  22. };  
template<typename Mutex>
class lock_guard
{
private:
    Mutex& m;

    explicit lock_guard(lock_guard&);
    lock_guard& operator=(lock_guard&);
public:
    explicit lock_guard(Mutex& m_):
        m(m_)
    {
        m.lock();
    }
    lock_guard(Mutex& m_,adopt_lock_t):
        m(m_)
    {}
    ~lock_guard()
    {
        m.unlock();
    }
};

      可以看到只有两个public方法,即构造和析构函数,也就是说,使用boost::lock_guard去guard一个mutex,必然是在boost::lock_guard的对象离开其作用域时unlock它所guard的mutex,不提供提前unlock的功能。
      而boost::unique_lock则提供这个功能,除了像boost::lock_guard一样在离开作用域时unlock它guard的mutex外,boost::unique还提供unlock函数,使用者可以手动执行unlock。此外,unique_lock还可以设置超时。

如果一个线程中可能在执行中需要再次获得锁的情况(例子:test_thread_deadlock),按常规的做法会出现死锁
此时就需要使用递归式互斥量boost::recursive_mutex,例子(test_thread_recursivelock)来避免这个问题。boost::recursive_mutex不会产生上述的死锁问题,只是是增加锁的计数,但必须确保你unlock和lock的次数相同,其他线程才可能锁这个mutex。

  1. namespace {  
  2.     boost::mutex g_mutex;    
  3.       
  4.     void threadfun1()  
  5.     {  
  6.         PRINT_DEBUG("enter threadfun1...");  
  7.         boost::lock_guard<boost::mutex> lock(g_mutex);  
  8.         PRINT_DEBUG("execute threadfun1...");  
  9.     }    
  10.       
  11.     void threadfun2()  
  12.     {  
  13.         PRINT_DEBUG("enter threadfun2...");  
  14.         boost::lock_guard<boost::mutex> lock(g_mutex);  
  15.         threadfun1();  
  16.         PRINT_DEBUG("execute threadfun2...");  
  17.     }  
  18. }  
  19.   
  20. namespace {  
  21.     boost::recursive_mutex g_rec_mutex;  
  22.   
  23.     void threadfun3()  
  24.     {  
  25.         PRINT_DEBUG("enter threadfun3...");  
  26.         boost::recursive_mutex::scoped_lock lock(g_rec_mutex);  
  27.         // 当然这种写法也可以   
  28.         // boost::lock_guard<boost::recursive_mutex> lock(g_rec_mutex);   
  29.         PRINT_DEBUG("execute threadfun3...");  
  30.     }    
  31.   
  32.     void threadfun4()  
  33.     {  
  34.         PRINT_DEBUG("enter threadfun4...");  
  35.         boost::recursive_mutex::scoped_lock lock(g_rec_mutex);  
  36.         threadfun3();  
  37.         PRINT_DEBUG("execute threadfun4...");  
  38.     }  
  39. }  
  40.   
  41. // 死锁的例子   
  42. void test_thread_deadlock()  
  43. {  
  44.     threadfun2();  
  45. }  
  46.   
  47. // 利用递归式互斥量来避免这个问题   
  48. void test_thread_recursivelock()  
  49. {  
  50.     threadfun4();  
  51. }  
namespace {
	boost::mutex g_mutex;  
	
	void threadfun1()
	{
		PRINT_DEBUG("enter threadfun1...");
		boost::lock_guard<boost::mutex> lock(g_mutex);
		PRINT_DEBUG("execute threadfun1...");
	}  
	
	void threadfun2()
	{
		PRINT_DEBUG("enter threadfun2...");
		boost::lock_guard<boost::mutex> lock(g_mutex);
		threadfun1();
		PRINT_DEBUG("execute threadfun2...");
	}
}

namespace {
	boost::recursive_mutex g_rec_mutex;

	void threadfun3()
	{
		PRINT_DEBUG("enter threadfun3...");
		boost::recursive_mutex::scoped_lock lock(g_rec_mutex);
		// 当然这种写法也可以
		// boost::lock_guard<boost::recursive_mutex> lock(g_rec_mutex);
		PRINT_DEBUG("execute threadfun3...");
	}  

	void threadfun4()
	{
		PRINT_DEBUG("enter threadfun4...");
		boost::recursive_mutex::scoped_lock lock(g_rec_mutex);
		threadfun3();
		PRINT_DEBUG("execute threadfun4...");
	}
}

// 死锁的例子
void test_thread_deadlock()
{
	threadfun2();
}

// 利用递归式互斥量来避免这个问题
void test_thread_recursivelock()
{
	threadfun4();
}


线程不是在任意时刻都可以被中断的。如果将线程中函数中的sleep()睡眠等待去掉,那么即使在主线程中调用interrupt()线程也不会被中断。
thread库预定义了若干个线程的中断点,只有当线程执行到中断点的时候才能被中断,一个线程可以拥有任意多个中断点。

thread库预定义了共9个中断点,它们都是函数,如下:

1. thread::join();
2. thread::timed_join();
3. condition_variable::wait();
4. condition_variable::timed_wait();
5. condition_variable_any::wait();
6. condition_variable_any::timed_wait();
7. thread::sleep();
8. this_thread::sleep();
9. this_thread::interruption_point()
这些中断点中的前8个都是某种形式的等待函数,表明线程在阻塞等待的时候可以被中断。

而最后一个位于子名字空间this_thread的interruption_point()则是一个特殊的中断点函数,它并不等待,只是起到一个标签的作用,表示线程执行到这个函数所在的语句就可以被中断。看看下面的例子:

  1. namespace  
  2. {  
  3.     boost::mutex io_mu;  
  4.   
  5.     void to_interrupt(const std::string& str)  
  6.     {  
  7.         // 如果在线程外部调用了this_thread->interrupt()   
  8.         // 线程内部的以下这些检查点可以抛出boost::thread_interrupted异常   
  9.         try  
  10.         {  
  11.             boost::this_thread::disable_interruption();  
  12.             for (int i = 0; i < 5; ++i)  
  13.             {  
  14.                 boost::mutex::scoped_lock lock(io_mu);  
  15.                 PRINT_DEBUG(i);  
  16.                 PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());  
  17.                 // PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_requested());   
  18.                 if (i == 2)  
  19.                 {  
  20.                     PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());  
  21.                     boost::this_thread::interruption_point();  
  22.                     PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());  
  23.                 }  
  24.             }  
  25.         }  
  26.         catch (boost::thread_interrupted &)  
  27.         {  
  28.         }  
  29.     }      
  30. }  
  31.   
  32. void test_thread_interrupt()  
  33. {  
  34.     boost::thread t(to_interrupt, "hello");  
  35.     // 中断函数   
  36.     t.interrupt();  
  37.     t.join();  
  38. }  
namespace
{
    boost::mutex io_mu;

    void to_interrupt(const std::string& str)
    {
        // 如果在线程外部调用了this_thread->interrupt()
        // 线程内部的以下这些检查点可以抛出boost::thread_interrupted异常
        try
        {
            boost::this_thread::disable_interruption();
            for (int i = 0; i < 5; ++i)
            {
                boost::mutex::scoped_lock lock(io_mu);
                PRINT_DEBUG(i);
                PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());
                // PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_requested());
                if (i == 2)
                {
                    PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());
                    boost::this_thread::interruption_point();
                    PRINT_DEBUG(std::boolalpha << boost::this_thread::interruption_enabled());
                }
            }
        }
        catch (boost::thread_interrupted &)
        {
        }
    }    
}

void test_thread_interrupt()
{
    boost::thread t(to_interrupt, "hello");
    // 中断函数
    t.interrupt();
    t.join();
}

运行结果:

  1. 2013-01-02 11:00:44 263 [8272] DEBUG - 0  
  2. 2013-01-02 11:00:44 266 [8272] DEBUG - 1  
  3. 2013-01-02 11:00:44 269 [8272] DEBUG - 2  
2013-01-02 11:00:44 263 [8272] DEBUG - 0
2013-01-02 11:00:44 266 [8272] DEBUG - 1
2013-01-02 11:00:44 269 [8272] DEBUG - 2

如果注释boost::this_thread::interrupt_point了,则结果如下:

  1. 2013-01-02 11:02:06 555 [5168] DEBUG - 0  
  2. 2013-01-02 11:02:06 559 [5168] DEBUG - 1  
  3. 2013-01-02 11:02:06 561 [5168] DEBUG - 2  
  4. 2013-01-02 11:02:06 564 [5168] DEBUG - 3  
  5. 2013-01-02 11:02:06 567 [5168] DEBUG - 4  
2013-01-02 11:02:06 555 [5168] DEBUG - 0
2013-01-02 11:02:06 559 [5168] DEBUG - 1
2013-01-02 11:02:06 561 [5168] DEBUG - 2
2013-01-02 11:02:06 564 [5168] DEBUG - 3
2013-01-02 11:02:06 567 [5168] DEBUG - 4

下面谈谈启用/禁用线程中断
缺省情况下钱程都是允许中断的,但thread库允许控制线程的中断行为。
thread 库在子名字空间this_thread提供了一组函数和类来共同完成线程的中断启用和禁用:
1. interruption_enabled(): 函数检测当前线程是否允许中断
2. interruption_requested(): 函数检测当前线程是否被要求中断
3. 类disable_interruption是一个RAII类型的对象,它在构造时关闭线程的中断,析构时自动恢复线程的中断状态。在disable_interruption 的生命期内线程始终是不可中断的,除非使用了restore_interruption 对象。
4. restore_interruption只能在disable_interruption 的作用域内使用,它在构造时临时打开线程的中断状态,在析构时又关闭中断状态。
这些中断点中的前8个都是某种形式的等待函数,表明线程在阻塞等待的时候可以被中断。

  1. namespace  
  2. {  
  3.     boost::mutex io_mu;  
  4.   
  5.     void to_interrupt_disable(const std::string& str)  
  6.     {  
  7.         // 默认可以中断   
  8.         assert(boost::this_thread::interruption_enabled());  
  9.           
  10.         for (int i = 0; i < 10; i++)  
  11.         {  
  12.             // 关闭中断   
  13.             boost::this_thread::disable_interruption di;            
  14.             // 此时中断不可用   
  15.             PRINT_DEBUG(std::boolalpha << "interruption_enabled = " <<  boost::this_thread::interruption_enabled());  
  16.             // 是否有中断请求   
  17.             PRINT_DEBUG(std::boolalpha << "interruption_requested = " <<  boost::this_thread::interruption_requested());  
  18.   
  19.             boost::mutex::scoped_lock lock(io_mu);  
  20.             PRINT_DEBUG(i);  
  21.             // 使用中断点函数,因为关闭中断,此时无效果。 中断恢复后,它才生效。   
  22.             boost::this_thread::interruption_point();  
  23.   
  24.             if (i == 8)  
  25.             {  
  26.                 // 临时恢复中断   
  27.                 boost::this_thread::restore_interruption ri(di);  
  28.                 PRINT_DEBUG(std::boolalpha << "interruption_enabled = " <<  boost::this_thread::interruption_enabled());  
  29.                 PRINT_DEBUG(std::boolalpha << "interruption_enabled after restore = " <<  boost::this_thread::interruption_enabled());  
  30.                 boost::this_thread::interruption_point();  
  31.             }  
  32.         }  
  33.     }  
  34. }  
  35.   
  36. void test_thread_interrupt_disable()  
  37. {  
  38.     boost::thread t(to_interrupt_disable, "hello");  
  39.     t.interrupt();  
  40.     t.join();  
  41. }  
namespace
{
	boost::mutex io_mu;

	void to_interrupt_disable(const std::string& str)
	{
		// 默认可以中断
		assert(boost::this_thread::interruption_enabled());
		
		for (int i = 0; i < 10; i++)
		{
			// 关闭中断
			boost::this_thread::disable_interruption di;          
			// 此时中断不可用
			PRINT_DEBUG(std::boolalpha << "interruption_enabled = " <<  boost::this_thread::interruption_enabled());
			// 是否有中断请求
			PRINT_DEBUG(std::boolalpha << "interruption_requested = " <<  boost::this_thread::interruption_requested());

			boost::mutex::scoped_lock lock(io_mu);
			PRINT_DEBUG(i);
			// 使用中断点函数,因为关闭中断,此时无效果。 中断恢复后,它才生效。
			boost::this_thread::interruption_point();

			if (i == 8)
			{
				// 临时恢复中断
				boost::this_thread::restore_interruption ri(di);
				PRINT_DEBUG(std::boolalpha << "interruption_enabled = " <<  boost::this_thread::interruption_enabled());
				PRINT_DEBUG(std::boolalpha << "interruption_enabled after restore = " <<  boost::this_thread::interruption_enabled());
				boost::this_thread::interruption_point();
			}
		}
	}
}

void test_thread_interrupt_disable()
{
	boost::thread t(to_interrupt_disable, "hello");
	t.interrupt();
	t.join();
}

结果:

  1. 2013-01-02 14:09:35 538 [7628] DEBUG - interruption_enabled = false  
  2. 2013-01-02 14:09:35 544 [7628] DEBUG - interruption_requested = true  
  3. 2013-01-02 14:09:35 551 [7628] DEBUG - 0  
  4. 2013-01-02 14:09:35 555 [7628] DEBUG - interruption_enabled = false  
  5. 2013-01-02 14:09:35 563 [7628] DEBUG - interruption_requested = true  
  6. 2013-01-02 14:09:35 570 [7628] DEBUG - 1  
  7. 2013-01-02 14:09:35 574 [7628] DEBUG - interruption_enabled = false  
  8. 2013-01-02 14:09:35 581 [7628] DEBUG - interruption_requested = true  
  9. 2013-01-02 14:09:35 586 [7628] DEBUG - 2  
  10. 2013-01-02 14:09:35 589 [7628] DEBUG - interruption_enabled = false  
  11. 2013-01-02 14:09:35 601 [7628] DEBUG - interruption_requested = true  
  12. 2013-01-02 14:09:35 608 [7628] DEBUG - 3  
  13. 2013-01-02 14:09:35 614 [7628] DEBUG - interruption_enabled = false  
  14. 2013-01-02 14:09:35 621 [7628] DEBUG - interruption_requested = true  
  15. 2013-01-02 14:09:35 627 [7628] DEBUG - 4  
  16. 2013-01-02 14:09:35 630 [7628] DEBUG - interruption_enabled = false  
  17. 2013-01-02 14:09:35 637 [7628] DEBUG - interruption_requested = true  
  18. 2013-01-02 14:09:35 643 [7628] DEBUG - 5  
  19. 2013-01-02 14:09:35 646 [7628] DEBUG - interruption_enabled = false  
  20. 2013-01-02 14:09:35 650 [7628] DEBUG - interruption_requested = true  
  21. 2013-01-02 14:09:35 655 [7628] DEBUG - 6  
  22. 2013-01-02 14:09:35 659 [7628] DEBUG - interruption_enabled = false  
  23. 2013-01-02 14:09:35 663 [7628] DEBUG - interruption_requested = true  
  24. 2013-01-02 14:09:35 667 [7628] DEBUG - 7  
  25. 2013-01-02 14:09:35 670 [7628] DEBUG - interruption_enabled = false  
  26. 2013-01-02 14:09:35 679 [7628] DEBUG - interruption_requested = true  
  27. 2013-01-02 14:09:35 685 [7628] DEBUG - 8  
  28. 2013-01-02 14:09:35 689 [7628] DEBUG - interruption_enabled = true  
  29. 2013-01-02 14:09:35 695 [7628] DEBUG - interruption_enabled after restore = true  
2013-01-02 14:09:35 538 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 544 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 551 [7628] DEBUG - 0
2013-01-02 14:09:35 555 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 563 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 570 [7628] DEBUG - 1
2013-01-02 14:09:35 574 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 581 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 586 [7628] DEBUG - 2
2013-01-02 14:09:35 589 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 601 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 608 [7628] DEBUG - 3
2013-01-02 14:09:35 614 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 621 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 627 [7628] DEBUG - 4
2013-01-02 14:09:35 630 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 637 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 643 [7628] DEBUG - 5
2013-01-02 14:09:35 646 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 650 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 655 [7628] DEBUG - 6
2013-01-02 14:09:35 659 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 663 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 667 [7628] DEBUG - 7
2013-01-02 14:09:35 670 [7628] DEBUG - interruption_enabled = false
2013-01-02 14:09:35 679 [7628] DEBUG - interruption_requested = true
2013-01-02 14:09:35 685 [7628] DEBUG - 8
2013-01-02 14:09:35 689 [7628] DEBUG - interruption_enabled = true
2013-01-02 14:09:35 695 [7628] DEBUG - interruption_enabled after restore = true


 

  1. namespace   
  2. {  
  3.     struct Run  
  4.     {  
  5.         void operator()(void)  
  6.         {  
  7.             std::cout << __FUNCTION__ << std::endl;  
  8.         }  
  9.     };  
  10.       
  11.     void run(void)  
  12.     {  
  13.         std::cout << __FUNCTION__ << std::endl;  
  14.     }  
  15. }  
  16.   
  17. void test_thread_group2()  
  18. {  
  19.     Run r;  
  20.     boost::thread_group grp;  
  21.   
  22.     // 两种方法通过线程组增加线程   
  23.     boost::thread *t = grp.create_thread(r);    // 使用create_thread   
  24.     grp.add_thread(new boost::thread(run)); // 使用add_thread   
  25.   
  26.     grp.join_all();  
  27.       
  28.     // 两种方法移除线程   
  29.     grp.remove_thread(t);  
  30.     // delete t;   
  31. }  
namespace 
{
	struct Run
	{
		void operator()(void)
		{
			std::cout << __FUNCTION__ << std::endl;
		}
	};
	
	void run(void)
	{
		std::cout << __FUNCTION__ << std::endl;
	}
}

void test_thread_group2()
{
	Run r;
	boost::thread_group grp;

	// 两种方法通过线程组增加线程
	boost::thread *t = grp.create_thread(r);	// 使用create_thread
	grp.add_thread(new boost::thread(run));	// 使用add_thread

	grp.join_all();
	
	// 两种方法移除线程
	grp.remove_thread(t);
	// delete t;
}


  1. namespace  
  2. {  
  3.     void wait(int seconds)  
  4.     {  
  5.         boost::this_thread::sleep(boost::posix_time::seconds(seconds));  
  6.     }  
  7.   
  8.     boost::mutex mu;  
  9.     boost::condition_variable_any cond;  
  10.   
  11.     void test_wait()  
  12.     {  
  13.         while(true)  
  14.         {  
  15.             boost::mutex::scoped_lock lock(mu);  
  16.             cond.wait(mu);  
  17.             PRINT_DEBUG(boost::this_thread::get_id() << "收到notify!");  
  18.         }  
  19.     }  
  20.   
  21.     void test_timed_wait() {  
  22.         while(true)  
  23.         {  
  24.             boost::mutex::scoped_lock lock(mu);  
  25.             if (cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::seconds(3)))   
  26.             {  
  27.                 PRINT_DEBUG("收到notify!");  
  28.             } else {  
  29.                 PRINT_DEBUG("超时, 没有收到Notify!");  
  30.             }  
  31.         }  
  32.     }  
  33. }  
  34.   
  35. void test_thread_wait()  
  36. {  
  37.     boost::thread t1(test_wait);  
  38.     boost::thread t2(test_wait);  
  39.     boost::thread t3(test_wait);  
  40.     boost::thread t4(test_wait);  
  41.     while (true)  
  42.     {  
  43.         wait(1);  
  44.         cond.notify_one();  
  45.     }  
  46. }  
  47.   
  48. void test_thread_timed_wait()  
  49. {  
  50.     boost::thread t1(test_timed_wait);  
  51.     while (true)  
  52.     {  
  53.         system("pause");  
  54.         cond.notify_one();  
  55.     }  
  56. }  
namespace
{
	void wait(int seconds)
	{
		boost::this_thread::sleep(boost::posix_time::seconds(seconds));
	}

	boost::mutex mu;
	boost::condition_variable_any cond;

	void test_wait()
	{
		while(true)
		{
			boost::mutex::scoped_lock lock(mu);
			cond.wait(mu);
			PRINT_DEBUG(boost::this_thread::get_id() << "收到notify!");
		}
	}

	void test_timed_wait() {
		while(true)
		{
			boost::mutex::scoped_lock lock(mu);
			if (cond.timed_wait(lock, boost::get_system_time() + boost::posix_time::seconds(3))) 
			{
				PRINT_DEBUG("收到notify!");
			} else {
				PRINT_DEBUG("超时, 没有收到Notify!");
			}
		}
	}
}

void test_thread_wait()
{
	boost::thread t1(test_wait);
	boost::thread t2(test_wait);
	boost::thread t3(test_wait);
	boost::thread t4(test_wait);
	while (true)
	{
		wait(1);
		cond.notify_one();
	}
}

void test_thread_timed_wait()
{
	boost::thread t1(test_timed_wait);
	while (true)
	{
		system("pause");
		cond.notify_one();
	}
}

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值