鉴于这个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 eyes\n"; }
};
/*Derived class*/
class Moe : public Stooge {
public:
Stooge* clone() { return new Moe; }
void slap_stick() {
cout << "Moe: slap head\n"; }
};
/*Derived class*/
class Curly : public Stooge {
public:
Stooge* clone() { return new Curly; }
void slap_stick() {
cout << "Curly: suffer abuse\n"; }
};
/*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()
吗?
答案 0 :(得分:1)
是的,提供的代码(尽管存在一些问题,错别字和更严重的问题)是线程安全的 - 从某种意义上说它没有线程竞争。对于特定的功能,问题“是线程安全的功能”很难回答。
代码没有线程竞争的原因很简单 - 整个程序中只有一个执行线程。使用修改后的问题,是的,你可以添加更多同时调用Factory::make_stooge
的线程,当前代码仍然没有的线程竞争。
答案 1 :(得分:0)
是的,您可以添加更多线程来创建Larry / Moe / Curly。但是这行代码: Stooge * Factory :: s_prototypes [] = { 0,新拉里,新萌,新卷曲 }; 甚至在你从用户那里获取输入之前就创建了Larry,Moe和Curly的实例,并且从未开始行动。但是,用户输入创建的实例存储在角色中。相反,我根本没有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;
}
答案 2 :(得分:-1)
可能是;但我不会赌它。
程序中的单个执行线程(程序不是线程安全的或不是线程安全的)不会使对象线程安全;因为您可能决定稍后添加一个帖子。
您的s_prototypes只能读取;在你要问的函数中,但它不是const。因此,可能会有一些改变它的东西。最重要的是,由于它们不是常量,因此也可能会改变这些原型的实例。
最后,克隆不是常量;这表明它可能正在改变对象中的某些东西。如果是这种情况,则线程安全的可能性要小得多; (并且在功能上没有可见性,无论如何都无法确认。)