【问题标题】:multithreading(pthread) compete code多线程(pthread)竞争代码
【发布时间】:2013-07-25 06:07:15
【问题描述】:
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
int global;
int i = 30; 
int j = 30; 
int k = 30; 
pthread_mutex_t mutex;
void* child1(void* arg)
{
    while(k--)
    {   
        pthread_mutex_lock(&mutex);
        global++;
        printf("from child1\n");
        printf("%d\n",global);
        pthread_mutex_unlock(&mutex);
    }   
}

void* child2(void* arg)
{
    while(j--)
    {   
        pthread_mutex_lock(&mutex);
        global++;
        printf("from child1\n");
        printf("%d\n",global);
        pthread_mutex_unlock(&mutex);
    }   
}

int main()
{

    pthread_t tid1, tid2;
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&tid1, NULL, child1, NULL);
    pthread_create(&tid2, NULL, child2, NULL);   
    while(i--)
    {
        pthread_mutex_lock(&mutex);
        global++;
        printf("from main\n");
        printf("%d\n",global);
        pthread_mutex_unlock(&mutex);
    }
    return 0;
}

我是pthread和多线程的新手,这段代码的结果是from main xxchild1很少出现,三个线程从来没有一起出现过,有什么问题?

【问题讨论】:

  • printf() 不一定会用换行符刷新输出,我不知道printf() 的底层实现如何在这里工作,但在你开始更难之前箍,我建议添加一个fflush(stdout) 以确保在每个线程的每次迭代中,输出缓冲区已在关键部分之间完全刷新,并且没有机会通过一些神奇的异步偶然事件被覆盖。如果简单的检查没有成功,那么请担心其他问题。

标签: c pthreads


【解决方案1】:

关键部分的大部分时间将花在printf 调用上。你可以试试:

{
    int local;

    pthread_mutex_lock(& mutex);
    local = ++global;
    pthread_mutex_unlock(& mutex);

    printf("from <fn>\n%d\n", local);
}

这仍然没有提供任何保证“公平”,但是printf 调用很可能使用将导致调度程序启动的系统调用或 I/O 事件在。


您的程序在许多方面与Dining Philosophers Problem 相似。您不希望任何线程“饿死”,但是您在线程之间争用全局计数器,并且您希望强制执行有序。

【讨论】:

  • 如何确保所有三个线程都已执行?
  • @nzomkxia - 你不能。您将需要一些其他 pthread 机制,可能是条件变量,或者使用 pthread_yield 的队列结构等。请查看餐饮哲学家问题。
  • 这里的全局计数器不是问题上下文中的共享资源,但是 - 它只是无限增加(除了行输出之外,没有任何分支或计算依赖于它的值) .每个线程都有自己的倒计时,它们共享的唯一资源是互斥锁。我看不出这与哲学家就餐问题有何相似之处。
  • 另外,iirc 的 C std lib 不是线程安全的,而且临界区之外的 printf 似乎要求输出缓冲区的竞争条件。
  • @Atash - POSIX 要求 printffprintf 等 - stdio 函数 - 是线程安全的,并且操作是 atomic 。这些是 POSIX 线程,我认为这不是问题。
【解决方案2】:

代码中的一个建议替换 printf("from child1\n");到 printf("来自 child2\n");在 void* child2(void* arg) 函数中。如果您想确保所有线程完成,请在 main 函数末尾添加以下行。 pthread_join(tid1,NULL); pthread_join(tid2,NULL);

【讨论】:

    【解决方案3】:

    我认为你应该使用 3 个不同的 mutex,顺便说一下使用 pconditional control 以避免不安全的访问

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-26
      • 2016-10-12
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多