C使用信号量和线程打印乒乓球

ved*_*905 3 c multithreading semaphore

我不确定我是否理解信号量和线程,因此我决定尝试一个相对简单的示例。我正在尝试有2个线程来交替打印,一个线程“ ping”另一个线程“ pong”,每个线程通知另一个线程是通过使用信号量完成的。但是,当我实现下面的代码时,它会先打印ping几百次,再打印几次pong,并稍作暂停。

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
sem_t pingsem;

void ping(){
    printf("Ping started\n");
    while(1){
        sem_wait(&pingsem);
        printf("ping\n");
        sem_post(&pingsem);
    }
}

void pong(){
    printf("Pong started\n");
    while(1){
        sem_wait(&pingsem);
        printf("pong\n");
        sleep(1);
        sem_post(&pingsem);
    }
}

int main(){
    sem_destroy(&pingsem);  //make sure the semaphore starts dead
    sem_init(&pingsem, 0, 1);  //initialize semaphore
    pthread_t ping_thread, pong_thread;  //start the threading
    pthread_create(&ping_thread, NULL, ping, NULL);
    pthread_create(&pong_thread, NULL, pong, NULL);
    pthread_join(ping_thread,NULL);
    pthread_join(pong_thread,NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我编译使用:

gcc stest.c -o stest -lpthread -lrt

没有错误或警告,但是当我运行它时,我得到:

$ ./stest
Ping started
ping
ping
ping
ping
Pong started
ping
ping
.
. hundreds of pings
.
ping
ping
ping
pong
pong
pong
pong
.
. hundreds of pongs
.
Run Code Online (Sandbox Code Playgroud)

它将最终关闭,但是为什么线程不交替打印其他线程?

cle*_*ght 5

您的示例中显示的问题是,这是一场竞赛,因为没有一个读取有效地阻塞了另一个。两个线程都在调度程序允许的情况下运行。按照其编码方式,每个线程可以在其时间片内自由运行(循环)多次,并满足其自己的信号量测试。在具有典型计划的多核/多CPU系统上,两个线程可以同时运行,并且可以任意任意地跨步执行。

这是一个工作正常的乒乓线程示例,该示例使用免费的信号量创建所需的乒乓互锁。

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

sem_t pingsem, pongsem;

void *
ping(void *arg) 
{
    for (;;) {
        sem_wait(&pingsem);
        printf("ping\n");
        sem_post(&pongsem);
    }
}

void *
pong(void *arg) 
{
    for (;;) {
        sem_wait(&pongsem);
        printf("pong\n");
        sem_post(&pingsem);
    }
}

int 
main(void) 
{
    sem_init(&pingsem, 0, 0);
    sem_init(&pongsem, 0, 1);
    pthread_t ping_thread, pong_thread; 
    pthread_create(&ping_thread, NULL, ping, NULL);
    pthread_create(&pong_thread, NULL, pong, NULL);
    pthread_join(ping_thread, NULL);
    pthread_join(pong_thread, NULL);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)