关于锁/条件变量这方面,没有经验。希望能向大家寻求一下指点

千梦一生 2020-05-13 05:12:12
搞TCP数据接收的时候遇到了,不可避免要搞这个。

我给队列的push/pop上了锁。
-----------------
在recv函数中
recv()
{
队列.push()//原子操作,不必担心

【std::condition_variable】->notify_one();//唤醒读取线程
}
这里是第一个问题:std::condition_variable的notify函数。我在脑袋里模拟了许久,感觉好像并不需要被锁住。这一点对吗?
-----------------------------------------------
另外一边thread函数
run()
{
while(!shutdown)
{
while(队列.为空)
【std::condition_variable】-> wait();

【不断地】队列.pop();
}
}
第二个问题是:这样写有问题吗?
------------------------------------------------
第三个问题:因此:std::condition_variable这玩意儿地这些操作并不需要上锁吗?无论何时?
...全文
179 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
千梦一生 2020-06-12
  • 打赏
  • 举报
回复
谢谢大家的帮助。在这方面受益匪浅,不过也需要些时机再多体会一番
我叫侯万楼 2020-05-15
  • 打赏
  • 举报
回复
参考:


#ifndef _SIMPLE_EVENT_H_
#define _SIMPLE_EVENT_H_

#include "typedef/DogInterger.h"
#include "noncopyable/noncopyable.h"
#include <chrono>
#include <mutex>
#include <condition_variable>

/** 简单事件
@note 不提供析构函数,如果当该类析构的时候,但是还处于Wait() 状态,很不幸的告诉你发生未定义行为
*/
class SimpleEvent :
    public NonCopyable
{
public:
    /** 等待一个信号
    */
    void Wait()
    {
        std::unique_lock<std::mutex> lck(m_mutex);

        if (!m_hasSignal)
        {
            // 不会死锁,考虑:
            // 1、m_mutex.unlock();
            // 2、wait()
            // 3、m_mutex.lock();
            // wait(lck) 相当于将1、2两步放到一个cpu周期内
            m_con.wait(lck);
        }

        m_hasSignal = false;
    }

    /** 超 时等待
    @param [in] timeOut 超 时 时 间
    @return 超时返回false,否者true
    */
    bool TimeWait(u32 timeOut)
    {
        std::unique_lock<std::mutex> lck(m_mutex);
        std::cv_status statu;
        if (!m_hasSignal)
        {
            // 不会死锁,考虑:
            // 1、m_mutex.unlock();
            // 2、wait()
            // 3、m_mutex.lock();
            // wait(lck) 相当于将1、2两步放到一个cpu周期内
            statu = m_con.wait_for(lck, std::chrono::milliseconds(timeOut));
        }

        m_hasSignal = false;
        return statu == std::cv_status::no_timeout;
    }

    /** 设置一个信号
    */
    void SetEvent()
    {
        std::unique_lock<std::mutex> lck(m_mutex);
        m_hasSignal = true;
        m_con.notify_all();
    }

private:
    /** 互斥量
    */
    std::mutex m_mutex;

    /** condition_variable
    */
    std::condition_variable m_con;

    /** 是否有信号,只是记录是否有信号,但是不记录信号次数
    @note 主要是为了先调用SetEvent(),然后调用wait的情况。考虑在Wait()前加上::Sleep(1000);
    */
    bool m_hasSignal = false;
};

#endif // _SIMPLE_EVENT_H_


若歌 2020-05-15
  • 打赏
  • 举报
回复
boost::mutex m; 上锁: boost::mutex::scoped_lock sl(m); variable.wait(m); 通知解锁: variable.notify_one();
qybao 2020-05-14
  • 打赏
  • 举报
回复
我觉得你是混淆了互斥锁mutex的使用 如果你自己直接操作互斥锁mutex.lock和unlock来加锁解锁,那就没必要用条件变量了。 你要用条件变量,就要给它一把锁(unique_lock),因为条件变量内部需要用这把锁来监控信号。 你可以参考一下互斥锁的使用 https://segmentfault.com/a/1190000006614695 再参考一下条件变量的使用 https://www.cnblogs.com/haippy/p/3252041.html 所以,你直接操作互斥锁,线程改成 thread1{ while(1) { int flag=0; 锁住 if(队列size<最大size){ 入队数据 flag=1; } 解锁 if(flag!=0) break;//退出while循环 } } thread2{ while(1) { int flag=0 锁住 if(队列size>0) { 出队数据 flag=1; } 解锁 if(flag!=0) break;//退出while循环 //否则继续while循环,相当于等待 } } 用条件变量,就是为了减少这些烦琐的控制。
ForestDB 2020-05-14
  • 打赏
  • 举报
回复
conditional variable总是和mutex配合使用的。
千梦一生 2020-05-14
  • 打赏
  • 举报
回复
引用 1 楼 qybao 的回复:
问题1
你这里的被锁住是指什么?是指用mutex来lock吗?你不lock的话,你的wait等待哪个锁呢?
问题2
你用条件变量,需要搭配unique_lock,否则你wait哪个锁?
问题3
需要上锁,你再谷歌百度相关资料,好好理解一下。

这位老师,上午好。
---------------------------------
我看了下别人的代码设计是:
thread1:
{
先锁住
入队数据
唤醒
函数返回前自动开锁/或根据需要选择何时开锁
}
thread2:
{
先锁住
while(空队列)
等待//函数阻塞时自动开锁,返回后上锁
出队数据
根据需要选择何时开锁
}
---------------------------------
我的理解是这样的:
mutex :互斥锁。mutex.lock->mutex.unlock。对公用资源【队列内存】的操作互斥,变相相当于【存、取成为了原子操作】
condition_variable:条件变量。wait阻塞线程,notify终止阻塞线程。

而我的设计是:
首先通过mutex保证对同一队列的读和取操作互斥、不会同时进行。在这里似乎已经保证线程安全了?
然后通过condition_variable处理顺序。消费者在队列无数据后,while()wait【阻塞等待】。生产者在产生数据后通过notify唤醒阻塞的消费者。
因此我的代码就是:
thread1:
{
先锁住
入队数据
这开锁

唤醒//不互斥
}
thread2:
{
while(空队列)
等待
锁住
出队数据
开锁

}
但是:condition_variable的wait函数需要调用者提供一把锁。我刚发现的。可这是为什么呢?
为什么这里wait函数一定要求给他锁呢?
qybao 2020-05-13
  • 打赏
  • 举报
回复
问题1 你这里的被锁住是指什么?是指用mutex来lock吗?你不lock的话,你的wait等待哪个锁呢? 问题2 你用条件变量,需要搭配unique_lock,否则你wait哪个锁? 问题3 需要上锁,你再谷歌百度相关资料,好好理解一下。

64,662

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧