【问题标题】:pthread mutex not working, getting a random value each timepthread互斥锁不起作用,每次都得到一个随机值
【发布时间】:2020-01-25 19:11:03
【问题描述】:

我正在学习 POSIX pthreads,在使用互斥锁时,我开始得到一个奇怪的输出。 每次我运行代码时,它都会输出一个随机数,而我希望它输出0。我检查了代码,但我无法弄清楚它发生的原因,所以如果有人能向我解释到底出了什么问题,我将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int num = 0;
pthread_mutex_t mutex;

void* add(void* args)
{
    int sign = *(int*) args;
    for(int i = 0; i < 100; i++)
    {
        pthread_mutex_lock(&mutex);
        num += sign;
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
    return NULL;
}


int main()
{
    pthread_t pool[1000];
    int plus = +1;
    int minus = -1;
    pthread_mutex_init(&mutex, NULL);


    for(int i = 0; i < 500; i++)
        pthread_create(&pool[i], NULL, add, &plus);

    for(int i = 500; i < 1000; i++)
        pthread_create(&pool[i], NULL, add, &minus);

    for(int i = 0; i < 1000; i++)
        pthread_join(pool[i], NULL);

    printf("%d", num);
    return 0;
}

【问题讨论】:

  • 在您假设互斥锁不起作用之前,请尝试使用合理的线程数(例如,每边 100、50)。根据平台的不同,单个进程中的一千个线程是一个延伸。而且由于这段代码中绝对没有任何错误检查,你真的不知道问题是什么。它可能与互斥锁无关。 pthread 函数的那些返回值意味着什么;使用它们。
  • @yxor pthread_create()失败后errno的值是多少?
  • 注意:大多数操作系统都设置为极大地限制线程数。
  • The proper way to initialize a pthread_mutex_t - 用pthread_mutex_init 初始化互斥锁同样有效。 so when calling pthread_join(), the code can skip those entries - 不,假设“0”对pthread_t 具有特殊含义,并且在pthread_join 中具有特殊含义,只是不可移植,并且对实现进行了假设。 pthread_t 是任何用于标识线程的抽象类型,the specification 没有多说什么。为了便于携带,只需使用另一个布尔数组。

标签: c pthreads mutex


【解决方案1】:

以下建议的代码:

  1. 干净编译
  2. 正确检查错误
  3. 正确初始化互斥体
  4. 执行所需的功能
  5. 导致输出为 0

注意:函数:pthread_mutex_init()是一个有效的函数,但NULL的初始值是无效的

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int num = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* add(void* args)
{
    int sign = *(int*) args;

    for(int i = 0; i < 100; i++)
    {
        pthread_mutex_lock(&mutex);
        num += sign;
        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(NULL);
}


int main( void )
{
    pthread_t pool[1000];
    int plus = +1;
    int minus = -1;


    for(int i = 0; i < 500; i++)
        if( pthread_create(&pool[i], NULL, add, &plus) != 0 )
        {
            perror( "pthread_create failed" );
            pool[i] = 0;
        }


    for(int i = 500; i < 1000; i++)
    {
        if( pthread_create(&pool[i], NULL, add, &minus) != 0 )
        {
            perror( "pthread-create failed" );
            pool[i] = 0;
        }
    }

    for(int i = 0; i < 1000; i++)
    {
        if( pool[i] )
        {
            pthread_join(pool[i], NULL);
        }
    }

    printf("%d", num);
    return 0;
}

在 linux 上运行建议的代码,结果:

0

【讨论】:

  • pool[i] = 0; - 我认为假设 pthread_t 是数字类型是不明智的。
  • 如果您真的担心类型,请使用:pool[i] = (pthread_t)0;
  • 将数值转换为类型在此上下文中不会改变任何内容。 pthread_t 可以是任何东西。它只是“碰巧”成为 glibc 中的算术类型。
  • 此代码无法使用标志 -Wall 和 -Werror 进行编译。 main.c: In function 'add': main.c:20:1: error: control reaches end of non-void function [-Werror=return-type] } ^ cc1.exe: all warnings being treated as errors
  • 你能修改它,这样我就不会收到这个警告吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 1970-01-01
  • 2012-06-05
  • 2013-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多