【问题标题】:output value interleavely with two pthreads与两个 pthread 交错输出值
【发布时间】:2013-11-24 18:37:01
【问题描述】:

我想创建两个输出交错的线程,如下所示

 Thread1:1=>Ping!
 Thread2:2=>Pong!
 Thread1:3=>Ping!
 Thread1:4=>Ping!
 Thread2:5=>Pong!
 Thread2:6=>Pong!
 Thread1:7=>Ping!
 Thread2:8=>Pong!
 Thread1:9=>Ping!
 ..........
 until 50

我的代码在下面

#include <stdio.h>
#include <stdlib.h> 
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
    //variable initialize
    pthread_t thread1, thread2;
    int res1 = 0, res2 = 0;
    int number = 0;
    int i = 0;
    //create semaphore
    if (sem_init(&sem, 0, 1) == -1){
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);     
    }
    for (i = 0; i < 25; ++i){
        //create thread
        res1 = pthread_create(&thread1, NULL, increment1, NULL);
        if (res1 != 0) {
            printf("Thread1 creation failed!!\n");
            exit(EXIT_FAILURE);
        }
        //wait thread synchronization
        pthread_join( thread1, NULL);
        res2 = pthread_create(&thread2, NULL, increment2, NULL);
        if (res2 != 0) {
            printf("Thread2 creation failed!!\n");
            exit(EXIT_FAILURE);
        }
        //wait thread synchronization
        pthread_join( thread2, NULL);
    }
        exit(EXIT_SUCCESS);
}
void* increment1(void* arg) { 
    sem_wait(&sem);
    count ++;
    printf("Thread1:%d\nPing!\n",count);
    fsync(fileno(stdout));
    sem_post(&sem);
}
void* increment2(void* arg) { 
    sem_wait(&sem);
    count ++;
    printf("Thread2:%d\nPong!\n",count);
    fsync(fileno(stdout));
    sem_post(&sem);
}

但我认为我所做的不是并行使用两个线程并且是错误的,我使用的是顺序替代执行两个线程并且它不是并行的。(通过使用pthread_join,thread2将在thread1之后执行完成)。

我尝试使用信号量,它似乎无法保证线程执行顺序。

我想问的是

1.如何使用信号量来保证两个线程的顺序?

2.如何暂停和恢复线程?我认为我所做的就是在一个循环循环中创建新的两个 pthread。

提前致谢。

【问题讨论】:

  • 只需创建两个线程一次。也许使用互斥量而不是信号量(信号量也可以像互斥量一样使用)。或者使用邮箱/队列在线程之间发送数据。
  • 每个线程都应该有自己的功能。线程阻塞在互斥锁或队列上...
  • 但是我如何保证第一次执行会被 ping 通?
  • 先创建它并给它时间先获取互斥锁...

标签: c linux multithreading pthreads posix


【解决方案1】:

添加第二个信号量并将其初始化为零,以便线程 1 被强制为第一个。然后increment1 和increment2 保持信号,它是其他线程轮流去。你在连接的地方遇到了一些小问题,你可以弄清楚。

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

void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;

int main()
{
    pthread_t thread[2];

    int res = 0;
    int number = 0;
    int i = 0;

    if (sem_init(&sem1, 0, 1) == -1)
    {
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);
    }

    if (sem_init(&sem2, 0, 0) == -1)
    {
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < 25; ++i)
    {
         res = pthread_create(&thread[0], NULL, increment1, NULL);
         if (res != 0)
         {
             printf("Thread creation failed!!\n");
             exit(EXIT_FAILURE);
         }

         res = pthread_create(&thread[1], NULL, increment2, NULL);
         if (res != 0)
         {
             printf("Thread creation failed!!\n");
             exit(EXIT_FAILURE);
         }

        for (int j = 0; j < 2; ++j)
        {
            pthread_join(thread[j], NULL);
        }
    }

    exit(EXIT_SUCCESS);
}

void* increment1(void* arg)
{
    sem_wait(&sem1);
    count ++;
    printf("Thread1:%d Ping!\n", count);
    fsync(fileno(stdout));
    sem_post(&sem2);
}

void* increment2(void* arg)
{
    sem_wait(&sem2);
    count ++;
    printf("Thread2:%d Pong!\n", count);
    fsync(fileno(stdout));
    sem_post(&sem1);
}

【讨论】:

  • 试图理解,如果线程在执行 sem_post() 之前通过执行 sem_wait() 获取/锁定的信号量之前被中断会发生什么行为,它会死锁吗?
  • @goldenmean,是的,它可能会出现死锁。任何重要的线程都应该有一些方法在关闭之前清理自己并释放资源,包括pthread_cleanup_push/pop 和取消机制。
【解决方案2】:

谢谢大家,我已经修改过了,看起来还不错。

#include <stdio.h>
#include <stdlib.h> 
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
    //variable initialize
    pthread_t thread1, thread2;
    int res1 = 0, res2 = 0;
    int number = 0;
    int i = 0;
    //create semaphore
    if (sem_init(&c_sem, 0, 1) == -1){
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);     
    }
    if (sem_init(&sem_1, 0, 1) == -1){
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);     
    }
    if (sem_init(&sem_2, 0, 0) == -1){
        printf("Semaphore creation failed!!\n");
        exit(EXIT_FAILURE);     
    }
    //create thread
    res1 = pthread_create(&thread1, NULL, increment_1, NULL);
    if (res1 != 0) {
        printf("Thread1 creation failed!!\n");
        exit(EXIT_FAILURE);
    }

    res2 = pthread_create(&thread2, NULL, increment_2, NULL);
    if (res2 != 0) {
        printf("Thread2 creation failed!!\n");  
        exit(EXIT_FAILURE);
    }

    //wait thread synchronization
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) { 
    while(1){
        sem_wait(&sem_1);
        sem_wait(&c_sem);
        if(count == 50){
            sem_post(&c_sem);
            sem_post(&sem_2);
            exit(EXIT_SUCCESS);
        }
        count ++;
        printf("Thread1:%d->Ping!\n",count);
        fsync(fileno(stdout));
        sem_post(&c_sem);
        sem_post(&sem_2);
    }
}
void* increment_2(void* arg) { 
    while(1){
        sem_wait(&sem_2);
        sem_wait(&c_sem);
        if(count == 50){
            sem_post(&c_sem);
            sem_post(&sem_1);   
            exit(EXIT_SUCCESS);     
        }
        count ++;
        printf("Thread2:%d->Pong!\n",count);
        fsync(fileno(stdout));
        sem_post(&c_sem);
        sem_post(&sem_1);

    }
}

【讨论】:

  • 试图理解,如果线程在执行 sem_post() 之前通过执行 sem_wait() 获取/锁定的信号量之前被中断会发生什么行为,它会死锁吗?
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-08
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多