这个接口是线程安全的吗?

Is this interface thread-safe?

本文关键字:安全 线程 接口      更新时间:2023-10-16

我想做一个控制循环接口。

具有should_stop()方法来检查循环是否应该断开或继续。

它确实侦听SIGINT信号(Ctrl+C),并且在它获得should_stop()信号后方法返回True。

现在看来这个接口工作正常了。

但是我不确定这个接口是线程安全的。

<标题> LoopInterface.h文件
#include "signal.h"
#include "pthread.h"
#define LOCK(mutex)     pthread_mutex_lock(&mutex)
#define UNLOCK(mutex)   pthread_mutex_unlock(&mutex)
class LoopInterface {
public:
    LoopInterface(){
        LOCK(_lock_is_signal_registered);
        bool temp = _is_signal_registered;
        UNLOCK(_lock_is_signal_registered);
        if(!temp)
        {
            register_signal();
        }
    }
    bool should_stop()
    {
        LOCK(_lock_should_stop);
        bool temp = _should_stop;
        UNLOCK(_lock_should_stop);
        return _should_stop;
    }
private:
    static void register_signal()
    {
        LOCK(_lock_is_signal_registered);
        _is_signal_registered = true;
        UNLOCK(_lock_is_signal_registered);
        signal(SIGINT, &LoopInterface::signal_handler);
    }
    static void signal_handler(int sig){
        LOCK(_lock_should_stop);
        _should_stop = true;
        UNLOCK(_lock_should_stop);
    }
    static bool _should_stop;
    static bool _is_signal_registered;
    static pthread_mutex_t _lock_should_stop, _lock_is_signal_registered;
};
<标题> LoopInterface.cpp文件
#include "LoopInterface.h"
bool LoopInterface::_should_stop = false;
bool LoopInterface::_is_signal_registered = false;
pthread_mutex_t LoopInterface::_lock_should_stop;
pthread_mutex_t LoopInterface::_lock_is_signal_registered;

这就是它的用法。

/************Threads*************/
#include "LoopInterface.h"
class A : public LoopInterface{
};
void threadX(){
    A a;
    while(!a.should_stop()){
        //do something...
    }
}

你能告诉我这个接口是线程安全的吗?或不呢?

如果没有,是什么问题?


<标题> 附加问题我的同步代码还有一个问题。

由于在signal_handler中调用pthread_mutex_lockshould_stop方法正在锁定同一个mutex,因此经常发生死锁。

我发现一篇文章指出线程相关的函数不应该在信号处理程序中调用。

我想我应该找另一种方法来同步我的成员变量

显然,这段代码不是线程安全的:变量_should_stop由某个不受控制的线程中的信号设置,并在运行自己线程的LoopInterface中读取。根本没有同步。这种方法只有在只有一个线程的情况下才是线程安全的。

您可以使用 使代码线程安全(相对于这个特定的变量)
static std::atomic<bool> _should_stop;

由于此时您对任何其他值都不感兴趣,因此可以读取带有std::memory_order_relaxed标志的变量。

如果LoopInterface的构造函数是从多个线程调用的,那么当然也需要同步访问_is_signal_registered