C++ 保护C++;具有pthread和引用的类

C++ 保护C++;具有pthread和引用的类,c++,multithreading,pthreads,C++,Multithreading,Pthreads,如果我有一个可能被后台线程修改的类的私有成员,并且有一个用于该私有成员的getter,那么我可以为getter使用对该私有成员的const引用,还是必须使用互斥来保护getter以确保安全?下面是一些示例代码。请注意,我没有使用C++11,因此无法访问这些功能。我知道std::atomic和std::lock\u guard及其用法,但我目前正在编写的代码使用C++03 值得注意的是,为了简单起见,shared_成员的int类型更像是占位符 如果有比get\u copyof\u shared\u

如果我有一个可能被后台线程修改的类的私有成员,并且有一个用于该私有成员的getter,那么我可以为getter使用对该私有成员的const引用,还是必须使用互斥来保护getter以确保安全?下面是一些示例代码。请注意,我没有使用C++11,因此无法访问这些功能。我知道
std::atomic
std::lock\u guard
及其用法,但我目前正在编写的代码使用C++03

值得注意的是,为了简单起见,shared_成员的int类型更像是占位符

如果有比get\u copyof\u shared\u int()方法更好的方法来确保安全性,我洗耳恭听。然而,如果参考资料是安全的,也会起作用,我只想确保安全

#include <pthread.h>

using namespace std;

class testclass{

public:

// return reference to shared_member (provided only as example of ideal getter)

    inline const int& get_shared_member () const{
        return shared_member;
    }

// return copy of shared_member (example of getter known to be thread safe )

    inline const int get_copyof_shared_int () {

        pthread_mutex_lock(&shared_int_mutex);

        int shared_member_copy = shared_member;

        pthread_mutex_unlock(&shared_int_mutex);

        return shared_member_copy;

    }

// initializes shared_member and mutex, starts running background_thread
    void init(int);

private:

    volatile int shared_member; //should be marked volatile because it is used in background_thread()

    pthread_mutex_t shared_int_mutex;

    // thread which may modify shared_member 

    static void *background_thread(void *arg);

};
#包括
使用名称空间std;
类testclass{
公众:
//返回对共享_成员的引用(仅作为理想getter的示例提供)
内联常量int&获取共享成员()常量{
返回共享成员;
}
//返回共享_成员的副本(已知线程安全的getter示例)
inline const int get_copyof_shared_int(){
pthread_mutex_lock(&shared_int_mutex);
int shared_member_copy=共享_member;
pthread_mutex_unlock(&shared_int_mutex);
返回共享成员副本;
}
//初始化共享_成员和互斥体,开始运行后台_线程
void init(int);
私人:
volatile int shared_member;//应标记为volatile,因为它在后台_thread()中使用
pthread_mutex_t shared_int_mutex;
//可以修改共享_成员的线程
静态void*背景线程(void*arg);
};

引用它本质上类似于传递指针(引用通常作为指针上的契约层实现)

这意味着不能保证线程在某个不方便的时间内读取值,例如当另一个线程在不同的内核上写入它时,

另外,您可能需要查看C++1的名称和标题

我还建议不要将getter内联到互斥对象中

const int get_copyof_shared_int () {

    std::lock_guard<std::mutex> lock(shared_int_mutex);

    return shared_int;

}
const int get\u copyof\u shared\u int(){
std::锁\保护锁(共享\内部\互斥);
返回共享整数;
}

不幸的是,从技术上讲,您应该保护getter,因为

至于getter,它看起来很简单,尽管我不确定为什么有两个不同的getter


编辑:不要忘记将共享变量标记为上面链接中指出的
volatile
。否则,优化编译器可能会进行一些不正确的优化,因为它可能会假定(在您的情况下是错误的)变量不会由另一个线程设置。

您需要使用一些同步机制(例如互斥)防止访问数据时出现争用情况。任何时候,当您有一个变量可以在单独的执行线程中读写时,您都应该提供同步/锁定保护,无论该变量是全局变量、类成员(静态或非静态)、堆栈变量,为C++11特性动态分配或任何…+1<代码>标准::原子可用于此情况。是的,我修改了我的问题,因为我正在处理的代码是C++03,所以没有std::lock\u guard或std::atomic。但是对于那些可以选择使用C++11的人来说,这两种方法都是非常好的!另外,我很欣赏关于使用互斥体内联getter的批评,因为我不完全理解何时/何时不内联,您是否有更详细的答案来解释为什么内联我的第二个(线程安全)getter不是最佳实践?内联:在大多数情况下,不要:由编译器决定。如果您已经完成了分析,告诉您编译器的选择不好,或者您正在创建一段复杂的代码,您确实希望编译器始终发出内联而不是使用函数,那么您只需要开始优化。对于互斥体,您正在创建一个资源瓶颈,可能是一个潜在条件分支。如果您完全知道它只会在一个地方被调用,那么内联提示可能很好,但鉴于它不是私有的,它看起来像是您将从代码周围的各个站点调用的东西。如果您已经完成了评测,并且发现getter的一些调用路径的争用频率与其他调用路径之间存在巨大差异,那么内联是可取的。否则,您的代码(和分支缓存)就会被互斥体的独特操作弄得乱七八糟。正如我在编辑中所阐明的,如果其他线程没有访问共享的_成员,那么第一个getter将是一个更理想的getter。感谢您提供有关volatile关键字的提示,以及指向其他问题的链接!这真的是太彻底了。