条件变量与互斥量(2)
因为线程的代码基本没怎么写过,leet-code出了线程题,刷下。
1116. 打印零与奇偶数
假设有这么一个类:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // 构造函数
public void zero(printNumber) { ... } // 仅打印出 0
public void even(printNumber) { ... } // 仅打印出 偶数
public void odd(printNumber) { ... } // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:
线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。
示例 1:
输入:n = 2
输出:"0102"
说明:三条线程异步执行,其中一个调用 zero(),另一个线程调用 even(),最后一个线程调用odd()。正确的输出为 "0102"。
示例 2:
输入:n = 5
输出:"0102030405"
VERSION 1:
三锁版,lock1, lock2, lock3. 线程a 激活线程b或者c, 线程b, c 激活线程a
由于glibc的版本低,改了pthread_once
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #define CHECK_VARIABLE(l,r) do{if(0 != r){fprintf(stderr,"[%s], err:[%d]\n",l,r);break;}}while(0); #define L pthread_mutex_t #define LOCK(t) pthread_mutex_lock(&t) #define UNLOCK(t) pthread_mutex_unlock(&t) #if 0 pthread_once_t tOnce = PTHREAD_ONCE_INIT; #endif int g_iOnce = 0; L tL0 = PTHREAD_MUTEX_INITIALIZER; /* zero odd even */ L tL1; L tL2; L tL3; void P(L* t) { while (pthread_mutex_lock(t) != 0) {} return ; } void V(L* t) { if (pthread_mutex_unlock(t) == -1) { fprintf (stderr, "[%s].\n" , "pthread_mutex_unlock error." ); } return ; } typedef struct { int n; } ZeroEvenOdd; ZeroEvenOdd* zeroEvenOddCreate( int n) { ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc ( sizeof (ZeroEvenOdd)); obj->n = n; return obj; } void threadOnceInit(){ int iRet = -1; iRet = pthread_mutex_init(&tL1, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); iRet = pthread_mutex_init(&tL2, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); iRet = pthread_mutex_init(&tL3, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); P(&tL2); P(&tL3); return ; } void zero(ZeroEvenOdd* obj) { int iRet = 0; int i = 0; P(&tL0); if (!g_iOnce) { threadOnceInit(); g_iOnce++; } V(&tL0); #if 0 iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); #endif for (; i < obj->n; i++) { P(&tL1); printNumber(0); if (i % 2) { V(&tL3); } else { V(&tL2); } } pthread_exit(NULL); } void odd(ZeroEvenOdd* obj) { int iRet = 0; int i = 1; P(&tL0); if (!g_iOnce) { threadOnceInit(); g_iOnce++; } V(&tL0); #if 0 iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); #endif for (; i <= obj->n; i += 2) { P(&tL2); printNumber(i); V(&tL1); } pthread_exit(NULL); } void even(ZeroEvenOdd* obj) { int iRet = 0; int i = 2; P(&tL0); if (!g_iOnce) { threadOnceInit(); g_iOnce++; } V(&tL0); #if 0 iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); #endif for (; i <= obj->n; i += 2) { P(&tL3); printNumber(i); V(&tL1); } pthread_exit(NULL); } void zeroEvenOddFree(ZeroEvenOdd* obj) { if (obj) { free (obj); obj = NULL; } return ; } |
高版本glibc支持pthread_once的code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <stdint.h> #include <math.h> #include <pthread.h> #include "leetcode.h" /* * leetcode 114: * Level : mid * 1116. Print Zero Even Odd * realize by state var and semaphore */ #define CHECK_VARIABLE(l,r) do{if(0 != r){fprintf(stderr,"[%s], err:[%d]\n",l,r);break;}}while(0); #define SET_BIT(x, y) (x |= (1<<y)) #define NEG_BIT(x, y) (x ^= (1<<y)) #define GET_BIT(x, y) ((x)>>y & 0x1) #define L pthread_mutex_t #define LOCK(t) pthread_mutex_lock(&t) #define UNLOCK(t) pthread_mutex_unlock(&t) pthread_once_t tOnce = PTHREAD_ONCE_INIT; /* zero odd even */ L tL1; L tL2; L tL3; void P(L* t) { while (pthread_mutex_trylock(t) != 0) {} return ; } void V(L* t) { if (pthread_mutex_unlock(t) == -1) { fprintf (stderr, "[%s].\n" , "pthread_mutex_unlock error." ); } return ; } void printNumber( int x) { printf ( "%d" , x); return ; } typedef struct { int n; } ZeroEvenOdd; ZeroEvenOdd* zeroEvenOddCreate( int n) { ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc ( sizeof (ZeroEvenOdd)); obj->n = n; return obj; } void threadOnceInit(){ int iRet = -1; iRet = pthread_mutex_init(&tL1, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); iRet = pthread_mutex_init(&tL2, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); iRet = pthread_mutex_init(&tL3, NULL); CHECK_VARIABLE( "tL1 init error." , iRet); P(&tL2); P(&tL3); return ; } void zero(ZeroEvenOdd* obj) { int iRet = 0; int i = 0; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); for (; i < obj->n; i++) { P(&tL1); printNumber(0); if (i % 2) { V(&tL3); } else { V(&tL2); } } pthread_exit(NULL); } void odd(ZeroEvenOdd* obj) { int iRet = 0; int i = 1; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); for (; i <= obj->n; i += 2) { P(&tL2); printNumber(i); V(&tL1); } pthread_exit(NULL); } void even(ZeroEvenOdd* obj) { int iRet = 0; int i = 2; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); for (; i <= obj->n; i += 2) { P(&tL3); printNumber(i); V(&tL1); } pthread_exit(NULL); } void zeroEvenOddFree(ZeroEvenOdd* obj) { if (obj) { free (obj); obj = NULL; } return ; } #define RETURN_IF_ERR(ret) \ if (0 != ret) { printf ( "Get errorcode = [%d] line = [%d].\n" , ret, __LINE__); return ret;} int main() { int iRet = 0; int * pvRet = NULL; pthread_t tTid1 = 0; pthread_t tTid2 = 0; pthread_t tTid3 = 0; ZeroEvenOdd* obj = NULL; #if 1 obj = zeroEvenOddCreate(10); RETURN_IF_ERR(obj == NULL); iRet = pthread_create(&tTid1, NULL, zero, obj); if (iRet) return iRet; iRet = pthread_create(&tTid2, NULL, odd, obj); if (iRet) return iRet; iRet = pthread_create(&tTid3, NULL, even, obj); if (iRet) return iRet; iRet = pthread_join(tTid1, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid2, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid3, NULL); RETURN_IF_ERR(iRet); zeroEvenOddFree(obj); pthread_mutex_destroy(&tL1); pthread_mutex_destroy(&tL2); pthread_mutex_destroy(&tL3); #endif return iRet; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <stdint.h> #include <math.h> #include <pthread.h> #include "leetcode.h" #define CHECK_VARIABLE(l,r) do{if(0 != r){fprintf(stderr,"[%s], err:[%d]\n",l,r);break;}}while(0); #define SET_BIT(x, y) (x |= (1<<y)) #define NEG_BIT(x, y) (x ^= (1<<y)) #define GET_BIT(x, y) ((x)>>y & 0x1) /* * leetcode 114: * Level : mid * 1116. Print Zero Even Odd * realize by state var and semaphore */ #define L pthread_mutex_t #define LOCK(t) pthread_mutex_lock(&t) #define UNLOCK(t) pthread_mutex_unlock(&t) int g_iGuide = 0; L tMutex; pthread_once_t tOnce = PTHREAD_ONCE_INIT; void P(L* t) { while (pthread_mutex_trylock(t) != 0) {} return ; } void V(L *t) { if (pthread_mutex_unlock(t) == -1) { fprintf (stderr, "[%s].\n" , "pthread_mutex_unlock error." ); } return ; } void printNumber( int x) { printf ( "%d" , x); return ; } typedef struct { int n; } ZeroEvenOdd; ZeroEvenOdd* zeroEvenOddCreate( int n) { ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc ( sizeof (ZeroEvenOdd)); obj->n = n; return obj; } void threadOnceInit(){ int iRet = -1; iRet = pthread_mutex_init(&tMutex, NULL); if (iRet) printf ( "pthread_mutex_init error.\n" ); return ; } /* do like this 0x000, 0x010, 0x100 */ void zero(ZeroEvenOdd* obj) { int iRet = 0; int i = 0; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tMutex); if (GET_BIT(g_iGuide, 0)) { V(&tMutex); continue ; } if (i < obj->n){ printNumber(0); } if (!GET_BIT(g_iGuide, 1)){ /* 000 -> 011 */ SET_BIT(g_iGuide, 1); } else if (!GET_BIT(g_iGuide, 2)){ /* 010 -> 111 */ SET_BIT(g_iGuide, 2); } else { sprintf (stderr, "[%s]\n" , "zero error." ); return ; } SET_BIT(g_iGuide, 0); V(&tMutex); i = i + 1; if (i > obj->n) break ; } pthread_exit(NULL); } void odd(ZeroEvenOdd* obj) { int iRet = 0; int i = 1; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tMutex); if (!GET_BIT(g_iGuide, 0) || GET_BIT(g_iGuide, 2)) { V(&tMutex); continue ; } if (i <= obj->n * 2) { printNumber((i + 1) / 2); } NEG_BIT(g_iGuide, 0); /* TODO: 010 -> 111 */ V(&tMutex); i = i + 4; if (i > obj->n * 2) break ; } pthread_exit(NULL); } void even(ZeroEvenOdd* obj) { int iRet = 0; int i = 2; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tMutex); if (!GET_BIT(g_iGuide, 0) || !GET_BIT(g_iGuide, 2)) { V(&tMutex); continue ; } if (i < obj->n * 2) { printNumber((i + 2) / 2); } g_iGuide = 0; V(&tMutex); i = i + 4; if (i >= obj->n * 2) break ; } pthread_exit(NULL); } void zeroEvenOddFree(ZeroEvenOdd* obj) { if (obj) { free (obj); obj = NULL; } return ; } #define RETURN_IF_ERR(ret) \ if (0 != ret) { printf ( "Get errorcode = [%d] line = [%d].\n" , ret, __LINE__); return ret;} int main() { int iRet = 0; int * pvRet = NULL; pthread_t tTid1 = 0; pthread_t tTid2 = 0; pthread_t tTid3 = 0; ZeroEvenOdd* obj = NULL; #if 1 obj = zeroEvenOddCreate(10); RETURN_IF_ERR(obj == NULL); iRet = pthread_create(&tTid3, NULL, odd, obj); if (iRet) return iRet; iRet = pthread_create(&tTid2, NULL, even, obj); if (iRet) return iRet; iRet = pthread_create(&tTid1, NULL, zero, obj); if (iRet) return iRet; iRet = pthread_join(tTid3, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid1, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid2, NULL); RETURN_IF_ERR(iRet); zeroEvenOddFree(obj); pthread_mutex_destroy(&tMutex); #endif return iRet; } |
使用 semaphore,不要问什么用这个,因为最早就是用semaphore,后发现测试机器不支持,才改用pthread_mutex_t
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <stdint.h> #include <math.h> #include <pthread.h> #include <semaphore.h> #include "leetcode.h" #define CHECK_VARIABLE(l,r) do{if(0 != r){fprintf(stderr,"[%s], err:[%d]\n",l,r);break;}}while(0); #define SET_BIT(x, y) (x |= (1<<y)) #define NEG_BIT(x, y) (x ^= (1<<y)) #define GET_BIT(x, y) ((x)>>y & 0x1) /* * leetcode 114: * Level : mid * 1116. Print Zero Even Odd * realize by state var and semaphore */ int g_iGuide = 0; sem_t tSem; pthread_once_t tOnce = PTHREAD_ONCE_INIT; void P(sem_t* sem) { while (sem_wait(sem) != 0) {} return ; } void V(sem_t *sem) { if (sem_post(sem) == -1) { fprintf (stderr, "[%s].\n" , "sem_post error." ); } return ; } void printNumber( int x) { printf ( "%d" , x); return ; } typedef struct { int n; } ZeroEvenOdd; ZeroEvenOdd* zeroEvenOddCreate( int n) { ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc ( sizeof (ZeroEvenOdd)); obj->n = n; return obj; } void threadOnceInit(){ int iRet = -1; iRet = sem_init(&tSem, 0, 1); if (iRet) printf ( "sem_init error.\n" ); return ; } /* do like this 0x000, 0x010, 0x100 */ void zero(ZeroEvenOdd* obj) { int iRet = 0; int i = 0; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tSem); if (GET_BIT(g_iGuide, 0)) { V(&tSem); continue ; } if (i < obj->n){ printNumber(0); } if (!GET_BIT(g_iGuide, 1)){ /* 000 -> 011 */ SET_BIT(g_iGuide, 1); } else if (!GET_BIT(g_iGuide, 2)){ /* 010 -> 111 */ SET_BIT(g_iGuide, 2); } else { sprintf (stderr, "[%s]\n" , "zero error." ); return ; } SET_BIT(g_iGuide, 0); V(&tSem); i = i + 1; if (i > obj->n) break ; } pthread_exit(NULL); } void odd(ZeroEvenOdd* obj) { int iRet = 0; int i = 1; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tSem); if (!GET_BIT(g_iGuide, 0) || GET_BIT(g_iGuide, 2)) { V(&tSem); continue ; } if (i <= obj->n * 2) { printNumber((i + 1) / 2); } NEG_BIT(g_iGuide, 0); /* TODO: 010 -> 111 */ V(&tSem); i = i + 4; if (i > obj->n * 2) break ; } pthread_exit(NULL); } void even(ZeroEvenOdd* obj) { int iRet = 0; int i = 2; iRet = pthread_once(&tOnce, threadOnceInit); CHECK_VARIABLE( "pthread_once error. \n" , iRet); while (1) { P(&tSem); if (!GET_BIT(g_iGuide, 0) || !GET_BIT(g_iGuide, 2)) { V(&tSem); continue ; } if (i < obj->n * 2) { printNumber((i + 2) / 2); } g_iGuide = 0; V(&tSem); i = i + 4; if (i >= obj->n * 2) break ; } pthread_exit(NULL); } void zeroEvenOddFree(ZeroEvenOdd* obj) { if (obj) { free (obj); obj = NULL; } return ; } #define RETURN_IF_ERR(ret) \ if (0 != ret) { printf ( "Get errorcode = [%d] line = [%d].\n" , ret, __LINE__); return ret;} int main() { int iRet = 0; int * pvRet = NULL; pthread_t tTid1 = 0; pthread_t tTid2 = 0; pthread_t tTid3 = 0; ZeroEvenOdd* obj = NULL; #if 1 obj = zeroEvenOddCreate(10); RETURN_IF_ERR(obj == NULL); iRet = pthread_create(&tTid3, NULL, odd, obj); if (iRet) return iRet; iRet = pthread_create(&tTid2, NULL, even, obj); if (iRet) return iRet; iRet = pthread_create(&tTid1, NULL, zero, obj); if (iRet) return iRet; iRet = pthread_join(tTid3, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid1, NULL); RETURN_IF_ERR(iRet); iRet = pthread_join(tTid2, NULL); RETURN_IF_ERR(iRet); zeroEvenOddFree(obj); #endif return iRet; } |
cond + mutex 最早用的,线程abc执行当满足条件时,否则竞争测试条件满足否。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | void printNumber( int x) { printf ( "%d" , x); return ; } typedef struct { int n; } ZeroEvenOdd; ZeroEvenOdd* zeroEvenOddCreate( int n) { ZeroEvenOdd* obj = (ZeroEvenOdd*) malloc ( sizeof (ZeroEvenOdd)); obj->n = n; return obj; } int g_iCurIndex = -1; pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t g_tCond = PTHREAD_COND_INITIALIZER; void zero(ZeroEvenOdd* obj) { int iRet = 0; while (1) { iRet = pthread_mutex_lock(&g_tMutex); if (iRet) continue ; while (g_iCurIndex % 2 != 0) { pthread_cond_wait(&g_tCond, &g_tMutex); } if (g_iCurIndex == obj->n * 2) { g_iCurIndex = 0; pthread_cond_broadcast(&g_tCond); pthread_mutex_unlock(&g_tMutex); /* free obj */ zeroEvenOddFree(obj); break ; } printNumber(0); g_iCurIndex++; pthread_mutex_unlock(&g_tMutex); pthread_cond_broadcast(&g_tCond); } pthread_exit(NULL); } void odd(ZeroEvenOdd* obj) { int iRet = 0; while (1) { iRet = pthread_mutex_lock(&g_tMutex); if (iRet) continue ; while ((g_iCurIndex % 2 == 0) || (g_iCurIndex % 4 != 1)) { pthread_cond_wait(&g_tCond, &g_tMutex); } iRet = g_iCurIndex; printNumber((iRet + 1) / 2); g_iCurIndex++; pthread_mutex_unlock(&g_tMutex); pthread_cond_broadcast(&g_tCond); if (iRet + 4 > obj->n * 2) break ; } pthread_exit(NULL); } void even(ZeroEvenOdd* obj) { int iRet = 0; while (iRet = pthread_mutex_lock(&g_tMutex) != 0); g_iCurIndex = 0; pthread_mutex_unlock(&g_tMutex); while (1) { iRet = pthread_mutex_lock(&g_tMutex); if (iRet) continue ; while ((g_iCurIndex % 2 == 0) || (g_iCurIndex % 4 != 3)) { pthread_cond_wait(&g_tCond, &g_tMutex); if (g_iCurIndex == 0) { pthread_exit(NULL); } } printNumber((g_iCurIndex + 1 ) / 2); iRet = g_iCurIndex; g_iCurIndex++; pthread_mutex_unlock(&g_tMutex); pthread_cond_broadcast(&g_tCond); if (iRet + 4 > obj->n * 2) break ; } pthread_exit(NULL); } void zeroEvenOddFree(ZeroEvenOdd* obj) { if (obj) { free (obj); obj = NULL; } return ; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步