I wrote the following code for leetcode question 1116. It's supposed to print out something like 01020304.... However my program is not printing anything now. I used the semaphore signals to post and wait signals and a variable to record current printing value.
#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);
}
What is the problem? Also is there a good way to debug this kind of problem using GDB?
The logic:
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.
so odd still thinks that obj->cur == 4 [ which is what it was when it went to sleep ]. There are two logical problems; even & odd terminate on <=, while zero terminates on <. Zero needs to 'unstick' the other one before exiting; so if last posted even, it needs to post odd.
Lastly, you are on thin ice by checking the condition without some form of synchronization; that means your check could be stale on the first iteration. In a simple counter case it doesn't matter, but a more complicated condition could be a problem, and your program contains no indication that it needs protection.
Try the following patch:
--- 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');
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.