我是C的新手,想了解比赛情况。我在互联网上找到了它,并要求找到竞争条件,并找到解决方案。
我的分析是,create-thread()方法中的竞争条件具有竞争条件,特别是在if-else
语句中。因此,当访问该方法时,可以在check-and-act
期间创建或删除另一个线程,并且thread_amt将关闭。
为了不具备竞争条件,请使用互斥锁,信号量等锁定if-else
?
如果我错了,任何人都可以纠正我,并且可能告诉我如何实现互斥?
#define MAXT 255
int threads_amt = 0;
int create-thread() // create a new thread
{
int tid;
if (threads_amt == MAXT) return -1;
else
{
threads_amt++;
return tid;
}
}
void release-thread()
{
/* release thread resources */
--threads_amt;
}
答案 0 :(得分:1)
是的,在这种情况下发生的竞争条件是因为您无法保证threads_amt
的检查和操作将在没有中断/执行另一个线程的情况下发生。
我头顶的三个解决方案:
1)使用二进制信号量(或互斥锁)强制互斥这部分代码以保护if-else部分。
2)使用初始值为MAXT的信号量,然后在调用create_thread时(注意,你不能在函数名中使用连字符!),使用" wait()" (取决于信号量的类型,它可以有不同的名称(例如sem_wait()))。之后,创建线程。调用release_thread()时,只需使用" signal()" (sem_post(),使用semaphore.h
时)。
3)这更像是一个硬件"解决方案:您可以假设您获得了执行整个if-else部分的原子函数,因此避免了任何竞争条件问题。
在这些解决方案中,最简单的"一个(基于你已经拥有的代码)是第一个。
让我们使用semaphore.h
的信号量:
#define MAXT 255
// Global semaphore
sem_t s;
int threads_amt = 0;
int main () {
...
sem_init (&s, 0, 1); // init semaphore (initial value = 1)
...
}
int create_thread() // create a new thread
{
int tid;
sem_wait(&s);
if (threads_amt == MAXT) {
sem_post(&s); // the semaphore is now available
return -1;
}
else
{
threads_amt++;
sem_post(&s); // the semaphore is now available
return tid;
}
}
void release_thread()
{
/* release thread resources */
sem_wait(&s);
--threads_amt;
sem_post(&s);
}
这应该可以正常工作。
我希望它清楚。如果不是,我建议您研究信号量如何工作(使用网络,或购买一些操作系统书)。另外,你提到你是C的新手:恕我直言,你应该从比这更简单的事情开始:信号量并不是你想要在“你好世界”之后学到的下一件事。 ; - )
答案 1 :(得分:0)
竞争条件不在if()
陈述中。
可以访问可能在多个线程中同时更改和访问的变量threads_amt
。
基本上,修改变量的任何线程都必须具有独占访问权限以避免竞争条件。这意味着必须同步修改变量或读取其值的所有代码(例如,首先获取互斥锁,然后释放)。读者不一定需要独占访问权限(例如,同时读取的两个线程不会相互影响)但是编写者会这样做(因此在尝试在另一个线程中更改它时避免读取值) - 这样的考虑因素可能有机会使用除互斥锁之外的同步方法 - 例如,信号量。
要使用互斥锁,必须先创建它(例如在项目启动期间)。然后在需要时抓住它,并记得在完成后释放它。每个函数都应该最小化它持有互斥锁的时间,因为其他尝试获取互斥锁的线程将被迫等待。
诀窍是无论何时发生互斥都无条件地抓取和释放互斥锁(即避免抓住互斥锁的功能,能够返回而不释放互斥锁)。这取决于你如何构建每个函数。
实现的实际代码取决于您使用的线程库(因此您需要阅读文档),但概念是相同的。所有线程库都具有创建,抓取(或输入)和释放互斥锁,信号量等功能。