c++11 实现信号量

简单来说,就是信号量太容易出错了(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();
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值