C信号量死锁

C信号量死锁,c,multithreading,pthreads,semaphore,C,Multithreading,Pthreads,Semaphore,我为leetcode问题1116编写了以下代码。它应该打印出像01020304这样的东西。。。。然而,我的程序现在没有打印任何内容。我使用信号量信号发布和等待信号,并使用变量记录当前打印值 #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <semaphore.h> typedef struct { int n; volatile int cu

我为leetcode问题1116编写了以下代码。它应该打印出像01020304这样的东西。。。。然而,我的程序现在没有打印任何内容。我使用信号量信号发布和等待信号,并使用变量记录当前打印值

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

typedef struct {
    int n;
    volatile int cur;
    sem_t szero;
    sem_t sodd;
    sem_t sevn;
} ZeroEvenOdd;

ZeroEvenOdd* zeroEvenOddCreate(int n) {
    ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc(sizeof(ZeroEvenOdd));
    obj->n = n;

    obj->cur = 1;
    sem_init(&obj->szero, 0, 1);
    sem_init(&obj->sodd, 0, 0);
    sem_init(&obj->sevn, 0, 0);
    return obj;
}

// You may call global function `void printNumber(int x)`
// to output "x", where x is an integer.

void printNumber(int x) {
    printf("%d", x);
}

void zero(ZeroEvenOdd* obj) {
    while(obj->cur<obj->n) {
        sem_wait(&obj->szero);
        printNumber(0);
        printNumber(obj->cur);
        if (obj->cur%2==1) {
            sem_post(&obj->sodd);
        } else {
            sem_post(&obj->sevn);
        }
    }
    
}

void even(ZeroEvenOdd* obj) {
    while(obj->cur<=obj->n){
        sem_wait(&obj->sevn);
        printNumber(obj->cur);
        obj->cur++;
        sem_post(&obj->szero);
    }
}

void odd(ZeroEvenOdd* obj) {
    while(obj->cur<=obj->n) {
        sem_wait(&obj->sodd);
        printNumber(obj->cur);
        obj->cur++;
        sem_post(&obj->szero);
    }
}

void zeroEvenOddFree(ZeroEvenOdd* obj) {
    if(NULL!=obj) {
        sem_destroy(&obj->szero);
        sem_destroy(&obj->sodd);
        sem_destroy(&obj->sevn);
        free(obj);
    }
}

int main() {
    ZeroEvenOdd *f=zeroEvenOddCreate(5);
    pthread_t tidz, tido, tide;

    pthread_create(&tidz, NULL, (void *)&zero, (void *)f);
    pthread_create(&tido, NULL, (void *)&odd, (void *)f);
    pthread_create(&tide, NULL, (void *)&even, (void *)f);

    

    pthread_join(tidz, NULL);
    pthread_join(tido, NULL);
    pthread_join(tide, NULL);
}
#包括
#包括
#包括
#包括
类型定义结构{
int n;
挥发性int-cur;
塞姆塞罗;
扫描电镜;
sem_t sevn;
}零偶奇数;
ZeroEvenOdd*zeroEvenOddCreate(整数n){
ZeroEvenOdd*obj=(ZeroEvenOdd*)malloc(sizeof(ZeroEvenOdd));
obj->n=n;
obj->cur=1;
sem_init(&obj->szero,0,1);
sem_init(&obj->sodd,0,0);
sem_init(&obj->sevn,0,0);
返回obj;
}
//您可以调用全局函数`void printNumber(int x)`
//输出“x”,其中x是一个整数。
无效打印编号(整数x){
printf(“%d”,x);
}
无效零(零偶数*obj){
while(obj->curn){
sem_wait(&obj->szero);
打印号码(0);
打印编号(obj->cur);
如果(对象->当前%2==1){
sem_post(&obj->sodd);
}否则{
sem_post(&obj->sevn);
}
}
}
空偶数(零偶数*obj){
while(obj->curn){
sem_wait(&obj->sevn);
打印编号(obj->cur);
obj->cur++;
sem_post(&obj->szero);
}
}
无效奇数(零偶数奇数*obj){
while(obj->curn){
sem_等待(&obj->sodd);
打印编号(obj->cur);
obj->cur++;
sem_post(&obj->szero);
}
}
void zeroEvenOddFree(ZeroEvenOdd*obj){
如果(NULL!=obj){
sem_销毁(&obj->szero);
sem_销毁(&obj->sodd);
sem_销毁(&obj->sevn);
免费(obj);
}
}
int main(){
ZeroEvenOdd*f=zeroEvenOddCreate(5);
pthread_t tidz,tido,tide;
pthread_创建(&tidz,NULL,(void*)&zero,(void*)f);
pthread_创建(&tido,NULL,(void*)和odd,(void*)f);
pthread_创建(&tide,NULL,(void*)和偶数,(void*)f);
pthread_join(tidz,NULL);
pthread_join(tido,NULL);
pthread_join(tide,NULL);
}
有什么问题?还有没有一种好方法可以使用GDB调试此类问题?

逻辑:

cur    n     zero           even           odd
 0     5     post(even)     print,sleep     -
 1     5     post(odd)      -              print,sleep
 2     5     post(even)     print,sleep     -
 3     5     post(odd)      -              print,sleep
 4     5     post(even)     print,exit      -
 5     5     exit.
所以奇数仍然认为obj->cur==4[这就是它睡觉时的样子]。
有两个逻辑问题;对于线程程序,最好使用来自代码不同部分的printf()语句来跟踪执行流和变量值更改。对于从多个线程对对象进行非同步、非只读、非原子访问的未定义行为。
--- s.c 2020-12-10 14:27:25.518641527 +0000
+++ s2.c    2020-12-10 14:28:15.358562490 +0000
@@ -29,23 +29,27 @@
     printf("%d", x);
 }
 
+void sig(ZeroEvenOdd* obj) {
+    if (obj->cur%2==1) {
+        sem_post(&obj->sodd);
+    } else {
+        sem_post(&obj->sevn);
+    }
+}
+
 void *zero(ZeroEvenOdd* obj) {
+    sem_wait(&obj->szero);
     while(obj->cur<obj->n) {
-        sem_wait(&obj->szero);
         printNumber(0);
         printNumber(obj->cur);
-        if (obj->cur%2==1) {
-            sem_post(&obj->sodd);
-        } else {
-            sem_post(&obj->sevn);
-        }
+   sig(obj);
+        sem_wait(&obj->szero);
     }
-   
-    
+    sig(obj);
 }
 
 void *even(ZeroEvenOdd* obj) {
-    while(obj->cur<=obj->n){
+    while(obj->cur<obj->n){
         sem_wait(&obj->sevn);
         printNumber(obj->cur);
         obj->cur++;
@@ -55,13 +59,13 @@
 }
 
 void *odd(ZeroEvenOdd* obj) {
-    while(obj->cur<=obj->n) {
+    while(obj->cur<obj->n) {
         sem_wait(&obj->sodd);
         printNumber(obj->cur);
         obj->cur++;
         sem_post(&obj->szero);
     }
-   
+
 }
 
 void zeroEvenOddFree(ZeroEvenOdd* obj) {
@@ -84,5 +88,5 @@
     pthread_join(tidz, NULL);
     pthread_join(tido, NULL);
     pthread_join(tide, NULL);
-
+    putchar('\n');
 }