【死锁】condition_variable导致一种死锁情况

声明了一个类,内部通过std::unique_ptr使用了muduo::net::TcpClient
 

class SendData
{
public:
	SendData();
	~SendData() = default;

private:
	void onConnection(const muduo::net::TcpConnectionPtr& conn)
	{
		// do something
		m_cv.notify_one()
	}

private:
	std::unique_ptr<muduo::net::TcpClient> m_pTcpClient;
	std::condition_variable m_cv
};

在程序内部创建了TcpClient,并连接了服务端。
连接断开的方法,采用了释放TcpClient对象的方式。

当TcpClient对象释放时会进行连接断开,此时会将连接结果通过回调函数反馈回来。
EventLoop反馈断开结果时,可能对象已经释放或者说condition_variable对象已经释放了。
回调函数还用的原来的地址执行了回调函数,此时执行到m_cv.notify_one可能会导致卡住
(linux_3.10 中通过gdb找到卡住的线程,通过调用堆栈是condition_variable中的__lll_lock_wait锁住)。
#0  0x00007ffff78c554d in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007ffff78c314d in pthread_cond_signal@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#2  0x00007ffff7b84b09 in std::condition_variable::notify_one() () from /lib64/libstdc++.so.6

=================================

通过写测试程序进行模拟,也没有模拟出来。如果有好的模拟方法,请指导。
 

#include <stdlib.h>
#include <stdio.h>

#include <condition_variable>
#include <thread>

int main()
{
    std::condition_variable *pcv;
    {
        std::condition_variable cv;
        pcv = &cv;
        for(int i = 0; i < 10; i++)
        {
            cv.notify_one();
            fprintf(stderr, "notify %d times.\n", i + 1);
        }
        cv.notify_all();
    }
    std::this_thread::sleep_for(std::chrono::seconds(1));
    pcv->notify_one();
    fprintf(stderr, "use dtor cv to notify_one.\n");

    return 0;
}

=================================
通过设置标志位来避免上述死锁的方式。当开始析构时设置标记位,回调函数发现了标志位,就直接退出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值