假设我有一个这样的类..这只是一个抽象代码
class foo
{
public:
int a;
static foo* pfoo;
foo()
{
pfoo = this;
}
fooCar* pFooCar;
void someMethod();
}
现在其他一些课可能会这样做
foo::pfoo->someMethod();
或
foo::pfoo->a = 14;
这种做法是否正确?
我应该将类的静态变量设为private并将静态变量的getter包装在互斥锁中吗?
像这样的东西
class foo
{
private:
static foo* pfoo;
public:
int a;
foo()
{
pfoo = this;
}
static foo* getFoo()
{
lock mutex..
return pfoo
unlock mutex..
}
fooCar* pFooCar;
void someMethod();
}
还有其他建议吗?
答案 0 :(得分:1)
首先,你的静态pfoo
基本上只是单身模式,所以你可以用{Meyers singleton'替换pfoo
这个东西,这是安全的(如果你想改变它)之后指针不适用):
class foo {
public:
static foo* getFoo() {
static foo singleton;
return &singleton;
}
};
但是,在收到指针后执行的任何都不能保证线程安全。但这一切都取决于你需要从代码中得到什么。根据应用程序的不同,线程安全会改变 lot ,尤其是读者和作者的数量。
现在,如果您只想让一个线程同时访问foo
个成员,那么您可以只使用一个互斥锁:
class foo {
std::mutex fooMutex;
int bar;
public:
static foo* getFoo() {
static foo singleton;
return &singleton;
}
void setBar(int newBar) {
std::lock_guard guard(fooMutex); //This goes in every function that modifies the data.
bar = newBar;
}
int getBar() {
std::lock_guard guard(fooMutex); //If simultaneous readers are allowed then remove this
return bar;
}
};
这完全取决于您的使用案例。这只是最简单,最天真,效率最低的方法。如果您需要根据其当前值更改bar
的值,则此操作无效。
答案 1 :(得分:0)
取决于您的设计要求。如果有相同类的对象在线程上处理某些共享数据,那么您需要显式处理同步线程对共享数据的访问。
在这种情况下,通过带锁的getter和setter公开成员变量是正确的。
答案 2 :(得分:0)
没有。静态变量初始化本身不是线程安全的。在一般情况下,在访问共享变量时应始终使用互斥锁/自旋锁。这不是原子的。
答案 3 :(得分:0)
不,你需要在一个原子步骤中将赋值包装到静态成员中;例如,临界区,互斥,InterlockedExchangePointer。虽然看起来这么简单的任务应该是线程安全的,但事实并非如此;即,赋值不是本机原子,可能会将部分分配的多字节变量暴露给另一个线程。
编辑:根据操作请求采样并删除令人困惑的段落
当然,您需要在使用互斥锁之前设置互斥锁
foo()
{
pthread_mutex_lock (&mutex);
pfoo = this;
pthread_mutex_unlock (&mutex);
}
static foo* getFoo()
{
foo *retval;
pthread_mutex_lock (&mutex);
retval = pfoo;
pthread_mutex_unlock (&mutex);
return retval;
}