【问题标题】:C - synchronizing multiple threads w/ mutexsC - 使用互斥锁同步多个线程
【发布时间】:2016-03-04 23:29:17
【问题描述】:

我正在尝试同步多个 (7) 线程。我以为我理解它们是如何工作的,直到我在我的代码上尝试它并且我的线程仍然乱序打印。代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
void *text(void *arg);
long code[] = {4,6,3,1,5,0,2}; //Order in which to start threads
int num = 0;
pthread_mutex_t lock; //Mutex variable

int main()
{
    int i;
    pthread_t tid[7];

    //Check if mutex worked
    if (pthread_mutex_init(&lock, NULL) != 0){
        printf("Mutex init failed\n");
        return 1;
    }

    //Initialize random number generator
    time_t seconds;
    time(&seconds);
    srand((unsigned int) seconds);

    //Create our threads
    for (i=0; i<7; i++)
        pthread_create(&tid[i], NULL, text, (void*)code[i]);

    //Wait for threads to finish
    for (i=0; i<7; i++){
        if(pthread_join(tid[i], NULL)){
            printf("A thread failed to join\n");
        }
    }    
    //Destroy mutex
    pthread_mutex_destroy(&lock);

    //Exit main
    return 0;
}

void *text (void *arg)
{
    //pthread_mutex_lock(&lock); //lock

    long n = (long) arg;
    int rand_sec = rand() % (3 - 1 + 1) + 1; //Random num seconds to sleep
    while (num != n) {} //Busy wait used to wait for our turn
    num++; //Let next thread go
    sleep(rand_sec); //Sleep for random amount of time

    pthread_mutex_lock(&lock); //lock
    printf("This is thread %d.\n", n);

    pthread_mutex_unlock(&lock); //unlock
    //Exit thread
    pthread_exit(0);
}

所以我在这里尝试按顺序打印线程 0-6,但现在它们仍然处于乱码状态。注释掉的互斥锁是我最初拥有它的位置,但随后将其移至 print 语句上方的行,但我得到了类似的结果。我不确定我的互斥锁中的错误在哪里,有人可以给我一个提示或指出我正确的方向吗?对此,我真的非常感激。提前致谢!

【问题讨论】:

  • 请解释为什么您认为您的线程应该“按顺序”打印?您所做的只是在 printf() 周围加了一个锁,无论如何它都有自己的内部锁。
  • @MartinJames 据我了解,锁会限制其他线程做任何事情,直到当前线程完成。
  • @donutjuice:那你理解的不对。 (成功)锁定互斥锁将阻止其他线程获取它,直到您释放它,仅此而已。与“直到当前线程完成”完全无关。而且由于您在尝试获取互斥锁之前让所有线程随机休眠一段时间,然后即使忽略您无法预测线程通常以何种顺序运行的事实,您也会竭尽全力尝试使它们不能按顺序运行。您对互斥锁所做的任何事情都不会阻止或试图阻止这种情况。
  • @PaulGriffiths 你能告诉我应该如何使用互斥锁吗?我尝试将锁放在函数的顶部(注释掉的 lock 语句),但是当我这样做时,没有打印任何线程。
  • @donutjuice:互斥锁用于同步对共享资源的访问,而不是用于同步线程的执行。您根本不应该将它们用于此目的。对num 的访问应该受到互斥锁的保护。您将线程的执行与条件变量同步。

标签: c multithreading pthreads mutex


【解决方案1】:

您不能仅使用互斥锁使线程按顺序运行,因为它们以不可预知的顺序执行。 在我的方法中,我使用条件变量和共享整数变量来创建排队系统。每个线程都有一个数字,当current_n 的数字等于实际线程的数字时,它进入临界区并打印它的数字。

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

#define N_THREAD 7

int current_n = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t number = PTHREAD_COND_INITIALIZER;


void *text (void *arg) {
   int i = (int)arg;

   pthread_mutex_lock(&mutex);
   while ( i > current_n ) {
      pthread_cond_wait(&number, &mutex);
   }

   //i = current_n at this point

   /*I use stderr because is not buffered and the output will be printed immediately.
     Alternatively you can use printf and then fflush(stdout).
   */
   fprintf(stderr, "I'm thread n=%d\n", i);
   current_n ++;

   pthread_cond_broadcast(&number);
   pthread_mutex_unlock(&mutex);
   return (void*)0;
}

int main() {
   pthread_t tid[N_THREAD];

   int i = 0;
   for(i = 0; i < N_THREAD; i++) {
      pthread_create(&tid[i], NULL, text, (void *)i);
   }

   for(i = 0; i < N_THREAD; i++) {
      if(pthread_join(tid[i], NULL)) {
        fprintf(stderr, "A thread failed to join\n");
      }
   }

   return 0;
}

输出是:

I'm thread n=0
I'm thread n=1
I'm thread n=2
I'm thread n=3 
I'm thread n=4
I'm thread n=5
I'm thread n=6

编译 gcc -Wall -Wextra -O2 test.c -o test -lpthread

不要担心警告。

【讨论】:

    猜你喜欢
    • 2014-05-02
    • 2021-06-04
    • 1970-01-01
    • 2020-12-07
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    相关资源
    最近更新 更多