我希望函式foo()等待陣列更新。該結構data包含foo()方法的引數。我附加foo()到一個執行緒,并且我在函式中有一個 while 回圈foo()來檢查何時updated是1(這意味著main()函式更改了陣列。它應該在發生這種情況時列印陣列。
這不會列印任何東西;該程式永遠停止。我對執行緒不太熟悉,所以我不知道這是否是正確的方法。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct data {
int array[5];
int updated;
};
pthread_cond_t cv;
pthread_mutex_t mp;
pthread_condattr_t cattr;
int ret;
void* foo(void* da) {
struct data* d = (struct data*)da;
while (d->updated == 0) {
pthread_mutex_lock(&mp);
if (d->updated == 1) {
pthread_cond_wait(&cv, &mp);
printf("Updated: ");
for (int i = 0; i < 5; i ) {
printf("%d ", d->array[i]);
}
printf("\n");
d->updated = 0;
}
pthread_mutex_unlock(&mp);
}
pthread_exit(NULL);
}
int main(void) {
pthread_t thread;
pthread_attr_t attr;
void *status;
struct data temp;
temp.updated = 0;
ret = pthread_cond_init(&cv, NULL);
ret = pthread_cond_init(&cv, &cattr);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&thread, NULL, foo, (void *) &temp);
int rc = pthread_join(thread, &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
pthread_mutex_lock(&mp);
for (i = 0; i < 5; i ) {
temp.array[i] *= 2;
}
temp.updated = 1;
pthread_mutex_unlock(&mp);
pthread_exit(NULL);
}
編輯:
在做出答案中建議的更改后,這就是我現在所擁有的。它正在列印陣列,但我希望它檢測陣列何時更改(即何時updated設定為true)。目前foo就像一個普通的非執行緒函式一樣。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int array[5] = {0,0,0,0,0};
pthread_cond_t cv;
pthread_mutex_t mp;
int updated = 0;
pthread_cond_t cv2;
pthread_mutex_t mp2;
int donePrinting = 0;
void* foo(void* a) {
pthread_mutex_lock(&mp);
int* arr = *(int**)a;
while (1) {
while (updated == 0)
pthread_cond_wait(&cv, &mp);
printf("Updated: ");
for (int i = 0; i < 5; i ) {
printf("%d ", arr[i]);
}
printf("\n");
updated = 0;
pthread_mutex_lock(&mp2);
donePrinting = 1;
pthread_cond_signal(&cv2); // Signal to main that we are done printing
pthread_mutex_unlock(&mp2);
}
pthread_mutex_unlock(&mp);
pthread_exit(NULL);
}
void changeArray(void) {
pthread_mutex_lock(&mp);
int i;
for (i = 0; i < 5; i ) {
array[i] = 2;
}
updated = 1;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mp);
}
int main(void) {
pthread_t thread;
void *status;
pthread_cond_init(&cv, NULL);
pthread_cond_init(&cv2, NULL);
pthread_mutex_init(&mp, NULL);
pthread_mutex_init(&mp2, NULL);
pthread_create(&thread, NULL, foo, &array);
// """"""""""""
// Change the array
changeArray();
// Wait for the second thread to finish printing
pthread_mutex_lock(&mp2);
while (!donePrinting)
pthread_cond_wait(&cv2, &mp2);
changeArray();
donePrinting = 0;
pthread_mutex_unlock(&mp2);
return 0;
// Change the array again
// Wait for the second thread to finish printing
pthread_mutex_lock(&mp2);
while (!donePrinting)
pthread_cond_wait(&cv2, &mp2);
donePrinting = 0;
changeArray();
pthread_mutex_unlock(&mp2);
// """"""""""""""""
int rc = pthread_join(thread, &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
pthread_exit(NULL);
}
uj5u.com熱心網友回復:
鎖定14小時。對此答案的評論已被禁用,但它仍在接受其他互動。了解更多。首先,線條
ret = pthread_cond_init(&cv, NULL);
ret = pthread_cond_init(&cv, &cattr);
錯了。pthread_cond_init對同一個條件變數呼叫兩次是沒有意義的cv。此外,如果您使用cattr,則應先初始化它,然后再將其傳遞給pthread_cond_init. 如果您想使用默認條件變數屬性,那么您應該簡單地傳遞NULL而不是&cattr. 你可能想做后者。在這種情況下,您應該簡單地洗掉第二行并洗掉cattr.
此外,您必須mp在使用前初始化互斥鎖,使用pthread_mutex_init.
線
int rc = pthread_join(thread, &status);
將導致主執行緒等待,直到第二個執行緒完成。但是,這永遠不會發生,因為這條線
temp.updated = 1;
第二個執行緒正在等待的,稍后在主執行緒中發生。因此,您應該移動
int rc = pthread_join(thread, &status);
行后:
temp.updated = 1;
pthread_cond_signal此外,您應該在該行之后添加一個呼叫
temp.updated = 1;
但在行前
int rc = pthread_join(thread, &status);
以便第二個執行緒得到通知,它應該再次檢查變數。
此外,在第二個執行緒中,該行
while (d->updated == 0) {
是錯誤的,因為執行該行時您沒有持有互斥鎖。這會導致未定義的行為(由于共享變數上的競爭條件)。
因此,如果要保持d->updated == 0回圈條件,則必須移動該行
pthread_mutex_lock(&mp);
行前:
while (d->updated == 0) {
這意味著您將有兩個重組回圈,因為 的位置pthread_mutex_unlock也必須在正確的位置。
但是,我懷疑保持d->updated == 0回圈條件是否合適。如果它應該是一個無限回圈,那么您可以撰寫for (;;)orwhile ( 1 )代替,這樣您就不會遇到在回圈條件下訪問共享變數的問題。
關于您更新的代碼,我相信這是該程式的作業版本,它可以完成您想要的一切:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int array[5] = {0};
pthread_cond_t cv;
pthread_mutex_t mp;
int updated = 0;
int terminate = 0;
pthread_cond_t cv2;
pthread_mutex_t mp2;
int donePrinting = 0;
void* foo(void* a) {
pthread_mutex_lock(&mp);
int* arr = a;
while ( 1 ) {
while ( updated == 0 && terminate == 0 )
pthread_cond_wait(&cv, &mp);
if ( terminate )
break;
printf("Updated: ");
for (int i = 0; i < 5; i ) {
printf("%d ", arr[i]);
fflush( stdout );
}
printf("\n");
fflush( stdout );
updated = 0;
pthread_mutex_lock(&mp2);
donePrinting = 1;
pthread_cond_signal(&cv2); // Signal to main that we are done printing
pthread_mutex_unlock(&mp2);
}
pthread_mutex_unlock(&mp);
pthread_exit(NULL);
}
void changeArray(void) {
pthread_mutex_lock(&mp);
int i;
for (i = 0; i < 5; i ) {
array[i] = 2;
}
updated = 1;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mp);
}
int main(void) {
pthread_t thread;
void *status;
pthread_cond_init(&cv, NULL);
pthread_cond_init(&cv2, NULL);
pthread_mutex_init(&mp, NULL);
pthread_mutex_init(&mp2, NULL);
pthread_create(&thread, NULL, foo, (void*)&array);
// """"""""""""
// Change the array
changeArray();
// Wait for the second thread to finish printing
pthread_mutex_lock(&mp2);
while (!donePrinting)
pthread_cond_wait(&cv2, &mp2);
pthread_mutex_unlock(&mp2);
//reset donePrinting
pthread_mutex_lock(&mp2);
donePrinting = 0;
pthread_mutex_unlock(&mp2);
// Change the array again
changeArray();
// Wait for the second thread to finish printing
pthread_mutex_lock(&mp2);
while (!donePrinting)
pthread_cond_wait(&cv2, &mp2);
pthread_mutex_unlock(&mp2);
//reset doneprinting
pthread_mutex_lock(&mp2);
donePrinting = 0;
pthread_mutex_unlock(&mp2);
// Change the array a third time
changeArray();
// """"""""""""""""
// Wait for the second thread to finish printing
pthread_mutex_lock(&mp2);
while (!donePrinting)
pthread_cond_wait(&cv2, &mp2);
pthread_mutex_unlock(&mp2);
//send terminate request
pthread_mutex_lock(&mp);
terminate = 1;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mp);
int rc = pthread_join(thread, &status);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
pthread_exit(NULL);
}
我更改了程式,以便主執行緒在處理完成并且沒有任何東西要發送時向第二個執行緒發送終止請求。
uj5u.com熱心網友回復:
您需要pthread_cond_signal在此程式中的某個時間點呼叫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/440250.html
