boost::this_thread::sleep_for()会死锁

(金庆的专栏)

发现睡眠1ms很容易死锁。
boost::this_thread::sleep_for(boost::chrono::milliseconds(1)).

Boost 1.54.0

以下代码很可能重现死锁:

#include "stdafx.h"

#include <iostream>
#include <boost/thread.hpp>

using namespace std;

void worker()
{
    for (int i = 0; i < 10000; i++)
        boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
}

int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread_group tg;
    for (int i = 0; i < 30; i++)
        tg.create_thread(worker);

    tg.join_all();
    cout << "All done!" << endl;
    return 0;
}

附加到死锁进程调试时,调用栈如下:
boost::this_thread::interruptible_wait() Line 547
boost::detail::basic_cv_list_entry::wait() Line 94
boost::detail::basic_condition_variable::do_wait<>() Line 228
boost::condition_variable::wait_until<>() Line 371
boost::this_thread::sleep_until<>() Line32
boost::this_thread::sleep_for<>() Line72
worker()
boost::detail::thread_data<>()

程序在停在thread.cpp:547:
    unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count, handles, false, using_timer?INFINITE:time_left.milliseconds);
其中    
handle_count = 2
using_timer = false
time_left.milliseconds = 0xfffffffe

发现 basic_cv_list_entry::wait(timeout abs_time) 当 abs_time.milliseconds = uint64(-1) 时就会死锁.
所在可以在此断点,将 abs_time.milliseconds 改为 uint64(-1),就可以重现死锁了.

实际上该参数很可能输入为-1:
        wait_until(...)
        {
          do_wait(lock, ceil<milliseconds>(t-Clock::now()).count());
          ...
        }

这几天改服务器代码,添加了许多 sleep_for(), 结果就经常发现服务器停止响应了。
幸好该错误仅在Windows上存在。错误位于 boost/thread/win32/condition_variable.hpp.

正准备给Boost添加条Bug记录,发现该错误已在3周前报告,10天前已修正,将在1.55.0版本中发布。
见:
Condition variable will wait forever for some timepoint values (MSVC)    
https://svn.boost.org/trac/boost/ticket/9079

修正代码如下:

    chrono::time_point<Clock, Duration> now = Clock::now();
    if (t<=now) {
      return cv_status::timeout;
    }
    do_wait(lock, ceil<milliseconds>(t-now).count());

boost::this_thread::sleep_for()死锁的更多相关文章

  1. 错误 4 error C2039: “Sleep”: 不是“boost::this_thread”的成员

    检查是否是在x64下运行的. #include <pcl/io/openni2_grabber.h> #include <pcl/visualization/cloud_viewer ...

  2. boost和C++11中的sleep

    boost boost线程中表示睡眠的函数有sleep和sleep_for sleep 例如: boost::this_thread::sleep(boost::posix_time::seconds ...

  3. (十)boost库之多线程

    (十)boost库之多线程 1.创建线程 使用boost库可以方便的创建一个线程,并提供最多支持9个参数的线程函数,相对于void*来说,方便了很多,创建线程主要提供了一下3种方式: 线程库头文件:# ...

  4. http客户端-基于boost开发

    http客户端-基于boost开发 基于BOOST编写的http客户端,作为BOOST开发学习之用.目前支持功能: http协议,单向链接返回http response code 200 可conte ...

  5. BOOST学习笔记

    BOOST学习笔记 1 tool #pragma once #include <vector> #include "boost/noncopyable.hpp" #in ...

  6. Debug EOS:nodeos + mongo_db_plugin

    上文书说到区块链的存储方式,并结合了EOSIO进行分析,其中也提到了使用CLion调试EOS的方法.本文将继续深入细致地展开对加载了mongo_db_plugin的nodeos的调试过程以及心得. 关 ...

  7. c++并发编程之条件变量(Condition Variable)

    条件变量(Condition Variable)的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒.经典的「生产者-消费者」问题就可以用条件 ...

  8. 搞定thrift双向消息

    thrift作为脱胎于facebook的rpc框架,各方面都非常优秀.清晰的分层设计,多语言的支持,以及不输protocolbuffer的效率(compact下优于protocolbuffer),都让 ...

  9. std::this_thread::yield/sleep_for

    std::this_thread::yield(): 当前线程放弃执行,操作系统调度另一线程继续执行.. std::this_thread::sleep_for(): 表示当前线程休眠一段时间,休眠期 ...

随机推荐

  1. 为什么选择C++

    为什么选择C++,怎么不选其它语言呢? 为什么不选择C? 因为C++比C简单点~ 为什么不选择C#? 因为C++可以在所有操作系统上使用. 为什么不选择JAVA? 因为C++的性能好一点~ 还有其他的 ...

  2. T-SQL注意事项(1)——SET NOCOUNT ON的去与留

    前言 用了一段时间T-SQL之后,哪怕自己没用过,也多多少少看过SSMS中的SET NOCOUNT ON命令,很多性能优化文章中都有提到这个东西,它们建议尽可能使用这个命令减少网络传输的压力,那么今天 ...

  3. 19 主线程向子线程发送信息(handler)

    package com.fmy.handler; import android.app.Activity; import android.os.Bundle; import android.os.Ha ...

  4. JAVA面向对象-----接口的特点

    接口的特点 1.类实现接口可以通过implements实现,实现接口的时候必须把接口中的所有方法实现,一个类可以实现多个接口. 2.接口中定义的所有的属性默认是public static final的 ...

  5. 没有文件扩展“.js”的脚本引擎问题解决

    安装MinGW的时候提示没有文件扩展".js"的脚本引擎. 原因:系统安装Dreamwear.UltraEdit.EditPlus后修改了.js文件的默认打开方式.当想直接执行js ...

  6. [maven学习笔记]第一节,认识maven,搭建maven开发环境,写第一个HelloWorld

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40142771 maven官网:http://maven.apache.org/ 学习视 ...

  7. antlr v4 使用指南连载3——g4文件概览

    g4文件概览        在深入介绍之前,有必要先给大家了解一下g4文件的结构,以便对如何编写语法规则文件有个全局的认识,我想这是大有禆益的.因为这样我们就可以很清晰地知道需要的东西写在哪里,或者哪 ...

  8. Servlet概述-servlet学习之旅(一)

    Servlet概述 servlet是server+applet的缩写.applet是运行于客户端浏览器的java小程序,java诞生的时候,因为applet而闻名于世,但是现在已经没有多少热使用了,而 ...

  9. Android下拉列表控件spinner-andoid学习之旅(十一)

    废话不多说,下拉列表常用的就是spinner控件. 直接上代码: package peng.liu.testview; import android.app.Activity; import andr ...

  10. SpringMVC源码分析--容器初始化(三)HttpServletBean

    在上一篇博客springMVC源码分析--容器初始化(二)DispatcherServlet中,我们队SpringMVC整体生命周期有一个简单的说明,并没有进行详细的源码分析,接下来我们会根据博客中提 ...