【问题标题】:how can i modify the threads to print " hello world again" ? in C如何修改线程以再次打印“hello world”?在 C 中
【发布时间】:2019-11-18 11:53:06
【问题描述】:

如何使用 lock_mutex 或 sleep 函数强制三个线程再次打印“hello world”?我已经完成了...

/* t2.c
       synchronize threads through mutex and conditional variable 
       To compile use: gcc -o t2 t2.c -lpthread 
    */

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

void hello(); // define three routines called by threads
void world();
void again(); /*new statment*/

/* global variable shared by threads */
pthread_mutex_t mutex; // mutex
pthread_cond_t done_hello; // conditional variable
int done = 0; // testing variable

int main(int argc, char* argv[])
{
    pthread_t tid_hello, // thread id
        tid_world, tid_again;

    /*  initialization on mutex and cond variable  */
    pthread_mutex_init(&mutex, NULL);

    pthread_cond_init(&done_hello, NULL);

    pthread_create(&tid_hello, NULL, (void*)&hello, NULL); //thread creation
    pthread_create(&tid_world, NULL, (void*)&world, NULL); //thread creation
    pthread_create(&tid_again, NULL, (void*)&again, NULL); //thread creation/*new statment*/
    /* main waits for the three threads to finish by order */
    pthread_join(tid_hello, NULL);

    pthread_join(tid_world, NULL);

    pthread_join(tid_again, NULL); /*new statment*/

    printf("\n");

    return 0;
}

void hello()
{
    pthread_mutex_lock(&mutex);

    printf(" hello");

    fflush(stdout); // flush buffer to allow instant print out
    done = 2;

    pthread_cond_signal(&done_hello); // signal world() thread
    pthread_mutex_unlock(&mutex); // unlocks mutex to allow world to print
    return;
}

void world()
{
    pthread_mutex_lock(&mutex);

    /* world thread waits until done == 1. */
    while (done == 1)
        pthread_cond_wait(&done_hello, &mutex);

    printf(" world");
    fflush(stdout);
    pthread_mutex_unlock(&mutex); // unlocks mutex
    return;
}

void again() /*new function*/
{
    pthread_mutex_lock(&mutex);

    /* again thread waits until done == 0. */
    while (done == 0)
        pthread_cond_wait(&done_hello, &mutex);

    printf(" again");
    fflush(stdout);
    pthread_mutex_unlock(&mutex); // unlocks mutex
    return;
}

【问题讨论】:

  • 不要将函数指针转换为void *,只需使用正确的原型void *hello(void *)
  • 当我使用你的原型时,会发生这个错误 t2.c:31:37: error: expected expression pthread_create (&tid_hello, NULL, void *hello(void *)
  • pthread_create 调用应如下所示:pthread_create(&amp;tid_hello, NULL, hello, NULL); 和函数void *hello(void *) { pthread_mutex_lock(&amp;mutex); ... }

标签: c linux ubuntu mutex


【解决方案1】:

是的,你可以。但是你应该使用几个pthread_cond_t 信号:

  • "hello" 已打印时的一个
  • "world" 已打印时的一个。

实际上,来自man pthread_cond_wait()

对同一条件变量使用多个互斥锁进行并发 pthread_cond_timedwait() 或 pthread_cond_wait() 操作的效果未定义;也就是说,当线程等待条件变量时,条件变量将绑定到唯一的互斥体,并且此(动态)绑定将在等待返回时结束。

每个worldagain 函数都必须等待自己的信号。

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

void * hello(void*);                   
void * world(void*);
void * again(void*);                   

/* global variable shared by threads */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;          
pthread_cond_t done_hello = PTHREAD_COND_INITIALIZER;      
pthread_cond_t done_world = PTHREAD_COND_INITIALIZER;      

int main(void)
{
    pthread_t threads[3];

    pthread_create(&threads[0], NULL, hello, NULL);    
    pthread_create(&threads[1], NULL, world, NULL);    
    pthread_create(&threads[2], NULL, again, NULL);    

    for(int i = 0; i < 3; ++i)
        pthread_join(threads[i], NULL);

    printf("\n");
    return 0;
}

void * hello(void* foo)
{
    pthread_mutex_lock(&mutex);
        printf(" hello");
        fflush(stdout);             
        pthread_cond_signal(&done_hello);
    pthread_mutex_unlock(&mutex);       
    return NULL;
}

void * world(void* foo)
{
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&done_hello, &mutex);
        printf(" world");
        fflush(stdout);
        pthread_cond_signal(&done_world);
    pthread_mutex_unlock(&mutex);       
    return NULL;
}

void * again(void* foo)
{                               
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&done_world, &mutex);
        printf(" again");
        fflush(stdout);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

【讨论】:

  • Nitpick:“但是你必须使用几个 pthread_cond_t 信号”并不完全正确。可以通过多种方式解决(包括使用单个 pthread_cond_t)。
  • @4386427:我不确定何时阅读了pthread_cond_wait 手册页。两个不同的线程可以毫无问题地等待同一个pthread_cond_t
  • 虽然有一些时间切片但是,很好的答案和你坐的解释
  • 两个线程可以同时等待,但在这种情况下可能需要pthread_cond_broadcast
  • 这不是如何使用 condvars。原版更接近。 condvar 没有内存,所以如果一个线程在没有其他线程等待时发出信号,那么没人会知道。
【解决方案2】:

要正确使用 condvar,请考虑以下几点:

void *thread(void *arg)
{
        static char str[] = { "hello", "world", "again" };
        int value = (int)(intptr_t)arg;
        /* wait for the condition (done == value) to be true */
        pthread_mutex_lock(&mutex);
        while (done != value) {
                pthread_cond_wait(&done_hello, &mutex);
        }
        pthread_mutex_unlock(&mutex);
        /* release all locks to decrease latency during our work */
        printf(" %s", str[value]);
        /* reacquire the lock to update done */
        pthread_mutex_lock(&mutex);
        done++;
        /* notify anybody that might be waiting for done */
        pthread_cond_broadcast(&done_hello);
        /* permit others to continue */
        pthread_mutex_unlock(&mutex);
        return NULL;
}

这与您的有点不同,但是让所有线程运行相同的代码可以建立对代码正确的信心,并减少在错误时进行调试的工作量。注意条件是如何使用的:lock(); while (!condition) wait(); unlock();lock(); setcondition(); broadcast(); unlock(); broadcast(); unlock(); 的顺序无关紧要,只要你在它们之间什么都不做。选择一个约定,并坚持下去;当你需要打破它时,它可以作为一个线索,表明正在发生一些事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 2014-01-10
    • 2012-10-06
    • 2015-05-04
    • 1970-01-01
    • 2015-02-28
    • 2020-02-03
    相关资源
    最近更新 更多