此工厂方法是否会导致争用条件?
Is this factory method causing a race condition?
鉴于此 c++ 代码段,在多个线程中使用Factory::make_stooge()
会导致争用条件吗? (原文摘自 https://sourcemaking.com/design_patterns/prototype/cpp/1)
/*Base class*/
class Stooge {
public:
virtual Stooge* clone() = 0;
virtual void slap_stick() = 0;
};
/*Factory class*/
class Factory {
public:
static Stooge* make_stooge( int choice );
private:
static Stooge* s_prototypes[4];
};
/*Derived class*/
class Larry : public Stooge {
public:
Stooge* clone() { return new Larry; }
void slap_stick() {
cout << "Larry: poke eyesn"; }
};
/*Derived class*/
class Moe : public Stooge {
public:
Stooge* clone() { return new Moe; }
void slap_stick() {
cout << "Moe: slap headn"; }
};
/*Derived class*/
class Curly : public Stooge {
public:
Stooge* clone() { return new Curly; }
void slap_stick() {
cout << "Curly: suffer abusen"; }
};
/*First thread function*/
void *make100Larrys(void *arg) {
Stooge** Larrys = (Stooge*)arg;
for(int i = 0; i<100; i++)
{
Larrys[i] = Factory::make_stooge(1);
}
pthread_exit();
}
/*Second thread function*/
void *make100Moes(void *arg) {
Stooge** Moes = (Stooge*)arg;
for(int i = 0; i<100; i++)
{
Moes[i] = Factory::make_stooge(2);
}
pthread_exit();
}
int main() {
vector<Stooge*> roles;
int choice;
while (true) {
cout << "Larry(1) Moe(2) Curly(3) Go(0): ";
cin >> choice;
if (choice == 0)
break;
roles.push_back(
Factory::make_stooge( choice ) );
}
for (int i=0; i < roles.size(); ++i)
roles[i]->slap_stick();
for (int i=0; i < roles.size(); ++i)
delete roles[i];
//Second Edit
pthread_t LarryThread;
Stooge* Larrys[100];
pthread_t MoeThread;
Stooge* Moes[100];
pthread_create(&LarryThread, NULL, make100Larrys, Larrys);
pthread_create(&MoeThread, NULL, make100Moes, Moes);
void** status;
pthread_join(LarryThread, status);
pthread_join(MoeThread, status);
}
/*Static variable initialization*/
Stooge* Factory::s_prototypes[] = {
0, new Larry, new Moe, new Curly
};
/*Factory method*/
Stooge* Factory::make_stooge( int choice ) {
return s_prototypes[choice]->clone();
}
我的想法是,如果在只有一个线程存在的情况下实例化s_prototypes
,则Factory::make_stooge()
在技术上是可重入的。
编辑:也许我的问题的更好措辞是:我可以在main()
中启动一些线程,每个线程都调用Factory::make_stooge()
?
是的,提供的代码(尽管它有几个问题,拼写错误和更严重的问题)是线程安全的 - 从某种意义上说,它没有线程竞赛。对于特定函数,"函数线程安全吗"的问题很少能得到回答。
代码没有线程争用的原因很简单 - 整个程序中只有一个线程执行。修改后的问题,是的,您可以添加更多可以同时调用Factory::make_stooge
线程,当前代码不会继续存在线程争用。
是的,您可以添加更多线程来创建 Larry/Moe/Curly。但是这行代码: 傀儡* 工厂::s_prototypes[] = { 0、新拉里、新萌、新卷毛 }; 创建拉里、萌和卷毛的实例,甚至在你从用户那里获得输入并且从未采取行动之前。但是,由用户输入创建的实例存储在角色中。相反,我根本不会s_prototypes并修改make_stooge:
Stooge *Stooge::make_stooge(int choice)
{
if (choice == 1)
return new Larry;
else if (choice == 2)
return new Moe;
else
return new Curly;
}
可能是; 但我不会打赌。
程序中的单个执行线程(程序是否线程安全)不会使对象线程安全;因为您可能决定稍后添加线程。
你的s_prototypes只被读取;在你询问的函数中,但它不是常量。 因此,引擎盖下可能会有一些东西改变它。 最重要的是,某些东西也可能改变这些原型的实例,因为它们也不是常量。
最后,克隆不是常量;这表明它可能正在改变对象中的某些内容。 如果是这种情况,那么线程安全的可能性要小得多;(并且该功能没有可见性,因此无法以任何一种方式确认)。
- 并行块(线程清理器)之外的 OpenMP 中的争用条件;误报?
- 如何在C++中创建争用条件
- C++上的手动重置事件(来自 C#)实现:如何避免争用条件
- 作为随机数生成器的争用条件
- 智能指针析构函数争用条件
- 尽管互斥锁,线程中的争用条件
- 在C++中递增和递减全局变量时的争用条件
- 为什么此代码不创建争用条件?
- __has_include() 和后续 #include 之间是否存在争用条件
- 什么保证两个不相关的线程中的不同不相关对象没有(不可避免的)争用条件?
- 此工厂方法是否会导致争用条件?
- 争用条件 2 个线程交替
- 标准::condition_variable 中可能存在的争用条件
- 启动子进程时的争用条件导致从管道读取挂起
- 当只有一个线程写入 c++ 中的布尔变量时,是否存在争用条件
- 避免在增加计数器时出现争用条件
- 是否有 std 或提升容器可以避免其插入和查找方法之间的争用条件
- 增强进程间争用条件预防
- pthread_once() 中的争用条件
- 发布标准实现争用条件