尝试使用pthread实现竞争条件

时间:2011-09-19 09:54:14

标签: c multithreading race-condition

我正在尝试设置竞争条件,看看它是如何理解的。我写了下面的代码。这个编译没有任何问题,但是当我运行它时,它不会在每次运行时打印计数。如果运行两次或三次,则打印计数。我的理解是正确的,在这段代码中,没有必要实际发生竞争条件。 (如果这是正确的,那么我不确定这是如何退出的,因为没有边界条件!)。如果我的理解不正确或代码,有人可以给我一些想法吗?

感谢。

#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值计数。

1 个答案:

答案 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;如果它不是空的 删除第一个作业,全部作为单个原子操作。