我正在尝试设置竞争条件,看看它是如何理解的。我写了下面的代码。这个编译没有任何问题,但是当我运行它时,它不会在每次运行时打印计数。如果运行两次或三次,则打印计数。我的理解是正确的,在这段代码中,没有必要实际发生竞争条件。 (如果这是正确的,那么我不确定这是如何退出的,因为没有边界条件!)。如果我的理解不正确或代码,有人可以给我一些想法吗?
感谢。
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
void *banking(void *);
int main(){
int accounts[2]={0,0};
pthread_t tid1,tid2;
if(pthread_create(&tid1,NULL,banking,(void *)accounts))
{
perror("pthread_create");
return 1;
}
if(pthread_create(&tid2,NULL,banking,(void *)accounts))
{
perror("pthread_create");
return 1;
}
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);//program now goes into infinite loop.
return 0;
}
void *banking(void * accounts){
int *ptr=accounts;
int count=0;
do{
int temp1=ptr[0];
int temp2=ptr[1];
int amount=rand();
ptr[0]=temp1-amount;
ptr[1]=temp2+amount;
//printf("%d \n %d\n",ptr[0],ptr[1]);
count++;
}while((ptr[0]+ptr[1])==0);
printf("%d\n",count);
//return NULL;
exit(0);
}
我试图实现pthread_exit(NULL)来实现线程在执行时退出的逻辑 - 虽然循环结束但是根据我的理解,其他正在运行的线程不会以这种方式停止,因为程序会运行进入无限循环。我意识到来自任何线程的exit()终止进程并合并exit(0)。代码适用于某些值,但随机生成两个不同的“计数”值。这种情况在10-12次尝试中发生一次。请建议是否建议在线程函数中使用exit,在什么情况下我会有两个diff值计数。
答案 0 :(得分:2)
1&GT;首先纠正“保罗R”已经出售的错误。那么
2 - ; 你需要使用pthread_join函数来成功完成两个线程..
在创建两个线程之后,主进程可能会被解决,所以当时两个线程也都已经结束,所以这个使用othread_join来为main()中的两个线程
将此代码添加到main()
的末尾pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
如果你还没有获得竞争条件的基础,那么请阅读下面的部分内容。我从一本参考书中复制了
假设您的程序有一系列由多个处理的排队作业 并发线程。作业队列由struct job的链表表示 对象。
每个线程完成一个操作后,它会检查队列以查看是否有其他操作 工作可用。如果job_queue为非null,则该线程将删除链接列表的头部 并将job_queue设置为列表中的下一个作业。 处理队列中作业的线程函数可能如代码清单4.10所示。 代码清单4.10(job-queue1.c)从队列中处理作业的线程函数
#include <malloc.h>
struct job {
/* Link field for linked list.
struct job* next;
*/
/* Other fields describing work to be done... */
};
/* A linked list of pending jobs.
struct job* job_queue;
*/
/* Process queued jobs until the queue is empty.
void* thread_function (void* arg)
{
while (job_queue != NULL) {
/* Get the next available job. */
struct job* next_job = job_queue;
/* Remove this job from the list. */
job_queue = job_queue->next;
/* Carry out the work. */
process_job (next_job);
/* Clean up. */
free (next_job);
}
return NULL;
}
*/
4.4
Synchronization and Critical Sections
现在假设两个线程几乎同时完成一项工作,但仅限于此 一个作业仍然在队列中。第一个线程检查job_queue是否为空;找- 如果不是,则线程进入循环并将指针存储到作业对象中 next_job。此时,Linux碰巧中断了第一个线程并安排了 second。第二个线程也检查job_queue并发现它为非null,也分配 指向next_job的相同作业指针。不幸的是,我们现在有两个 线程执行相同的工作。
更糟糕的是,一个线程将取消作业对象与队列的链接, 让job_queue包含null。当另一个线程评估job_queue-&gt; next时, 将导致分段错误。
这是竞争条件的一个例子。在“幸运”的情况下,这个特别 两个线程的时间表可能永远不会发生,并且竞争条件可能永远不会发生 表现自己。只有在不同的情况下,也许在大量运行时 加载系统(或在重要客户的新多处理器服务器上!)可能 bug表现出来。
要消除竞争条件,您需要一种使操作成为原子的方法。一个原子 操作是不可分割的,不可中断的;一旦操作开始,它就不会 暂停或中断直至完成,并且不会发生任何其他操作 - 而。在此特定示例中,您要检查job_queue;如果它不是空的 删除第一个作业,全部作为单个原子操作。