c++11 实现信号量

来源:互联网 发布:c 获取数据库实例名 编辑:程序博客网 时间:2024/06/05 04:23

简单来说,就是信号量太容易出错了(too error prone),通过组合互斥锁(mutex)和条件变量(condition variable)可以达到相同的效果,且更加安全。实现如下:

class Semaphore {public:  Semaphore(long count = 0)    : count_(count) {  }  void Signal() {    boost::unique_lock<boost::mutex> lock(mutex_);    ++count_;    cv_.notify_one();  }  void Wait() {    boost::unique_lock<boost::mutex> lock(mutex_);    cv_.wait(lock, [=] { return count_ > 0; });    --count_;  }private:  boost::mutex mutex_;  boost::condition_variable cv_;  long count_;};

下面创建三个工作线程(Worker),来测试这个信号量。

int main() {  boost::thread_group threads;  for (int i = 0; i < 3; ++i) {    threads.create_thread(&Worker);  }  threads.join_all();  return 0;}

每个工作线程先等待信号量,然后输出线程 ID 和当前时间,输出操作以互斥锁同步以防止错位,睡眠一秒是为了模拟线程处理数据的耗时。

void Worker() {  g_semaphore.Wait();  boost::thread::id thread_id = boost::this_thread::get_id();  std::string now = FormatTime(boost::posix_time::second_clock::local_time(), "%H:%M:%S");  {    boost::lock_guard<boost::mutex> lock(g_io_mutex);    std::cout << "Thread " << thread_id << ": wait succeeded" << " (" << now << ")" << std::endl;  }  // Sleep 1 second to simulate data processing.  boost::this_thread::sleep(boost::posix_time::seconds(1));  g_semaphore.Signal();}

信号量本身是一个全局对象,count 为 1,一次只允许一个线程访问:

Semaphore g_semaphore(1);

输出为:

Thread 1d38: wait succeeded (13:10:10)Thread 20f4: wait succeeded (13:10:11)Thread 2348: wait succeeded (13:10:12)

可见每个线程相隔一秒,即一次只允许一个线程访问。如果把 count 改为 3

Semaphore g_semaphore(3);

那么三个线程输出的时间应该一样:

Thread 19f8: wait succeeded (13:10:57)Thread 2030: wait succeeded (13:10:57)Thread 199c: wait succeeded (13:10:57)

最后附上 FormatTime 函数的实现:

std::string FormatTime(boost::posix_time::ptime& time, const char* format) {  std::stringstream stream;  boost::posix_time::time_facet* facet = new boost::posix_time::time_facet();  facet->format(format);  stream.imbue(std::locale(std::locale::classic(), facet));  stream << time;  return stream.str();}