2017-08-24 34 views
0

好吧,我已經定義了2個互斥體:bar_mutex(在N個線程之間使用)和writer_mutex(在線程中用於監視線程)。作家互斥被用於避免變量k_total奇怪的值,那裏我正在修改一個全局變量,但在某些特定時刻變量變爲0.0,另一個線程使用它的值。 爲了避免我添加了writer_mutex,但問題仍然存在。我究竟做錯了什麼?我將粘貼代碼的重要部分。pthread mutexes中的意外行爲

if (k_total < 1 && b->cm <=20) { 
    b->cm = b->cm + 10; //Usando este valor calculamos el deltak 
    /* printf("\nThread yendo hacia abajo\n"); */ 
    if (b->direction == UP) { 
     b->direction = DOWN; 
     changed_direction = true; 
    } else { 
     changed_direction = false; 
    } 
} else if(k_total > 1 && b->cm >=-20) { 
    b->cm = b->cm - 10; //Usando este valor calculamos el deltak 
    /* printf("\nThread yendo hacia arriba\n"); */ 
    if (b->direction == DOWN) { 
     b->direction = UP; 
     changed_direction = true; 
    } else { 
     changed_direction = false; 
    } 
} 

在功能move_bar k_total的這一部分被視爲0,而不是 正確的價值......爲了避免這種我加入了writer_mutex但它仍然沒有工作

enter image description here

在這裏你可以看到全局變量KTOTAL在一些01發送爲點...我試圖避免這一點。

我會追加代碼的主要部分。

void 
start_threads(struct bar* bars) { 
    int i; 
    pthread_t threads[NUM_THREADS + 1]; 
    bars = (struct bar*)malloc(sizeof(struct bar) * NUM_THREADS); 
    init_variables(); 
    pthread_mutex_init(&bar_mutex, NULL); 
    pthread_mutex_init(&write_mutex, NULL); 
    pthread_cond_init(&unstable_state, NULL); 

    for (i = 1; i < NUM_THREADS + 1; i++) { 
     fill_bar(&bars[i - 1], i); 
    } 

    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    // creating the 4 threads that handle each bar 
    for (i = 0; i < NUM_THREADS; i++) { 
     pthread_create(&threads[i], &attr, move_bar, (void *)&bars[i]); 
    } 
    //thread used to check if system is stable and change its k_total 
    pthread_create(&threads[NUM_THREADS], &attr, check_stable, (void*)bars); 

    /* Wait for all threads to complete */ 
    for (i=0; i<NUM_THREADS + 1; i++) { 
     pthread_join(threads[i], NULL); 
    } 
} 

void* 
check_stable(void* bars) { 
    struct bar* wires = (struct bar*) bars ; 
    while (true) { 
     pthread_mutex_lock(&write_mutex); 
     k_total = 0.0; 
     for (int i = 0; i < NUM_THREADS; ++i) { 
      k_total += getDeltaKValue(wires[i].cm); 
     } 

     char str[25]; 
     sprintf(str,"deltak=%lf", k_total); 
     doPost("deltak",str); 

     k_total = k_value + k_total; 

     sprintf(str,"kparcial=%lf",k_value); 
     doPost("kparcial",str); 
     sprintf(str,"ktotal=%lf", k_total); 
     doPost("ktotal",str); 
     if ((double)k_total != (double)1.0) { 
      unbalanced = true; 
      pthread_cond_signal(&unstable_state); 
     } else { 
      unbalanced = false; 
     } 
     pthread_mutex_unlock(&write_mutex); 
     sleep(1); 
    } 
} 

void* 
move_bar(void *bar) { 
    struct bar* b = (struct bar*) bar; 
    clock_t start = clock(); 
    bool changed_direction = false; 
    while (true) { 
     pthread_mutex_lock(&bar_mutex); 
     while (unbalanced == false) 
      pthread_cond_wait(&unstable_state, &bar_mutex); 
     pthread_mutex_lock(&write_mutex); 
     if (k_total < 1 && b->cm <=20) { 
      b->cm = b->cm + 10; //Usando este valor calculamos el deltak 
      /* printf("\nThread yendo hacia abajo\n"); */ 
      if(b->direction == UP) { 
       b->direction = DOWN; 
       changed_direction = true; 
      } else { 
       changed_direction = false; 
      } 
     } else if (k_total > 1 && b->cm >=-20) { 
      b->cm = b->cm - 10; //Usando este valor calculamos el deltak 
      /* printf("\nThread yendo hacia arriba\n"); */ 
      if(b->direction == DOWN) { 
       b->direction = UP; 
       changed_direction = true; 
      } else { 
       changed_direction = false; 
      } 
     } 

     k_total = 0.0; 
     for (int i = 0; i < NUM_THREADS; ++i) { 
      k_total += getDeltaKValue(bars[i].cm); 
     } 
     char str[25]; 
     if ((double)k_total != (double)1.0) { 
      unbalanced = true; 
     } else { 
      printf("\nBALANCED"); 
      unbalanced = false; 
     } 

     pthread_mutex_unlock(&write_mutex); 

     if (changed_direction) { 
      sleep(CHANGE_DIRECTION); 
     } 
     sleep(MOVEMENT_TIME); 

     sprintf(str,"id=%ld&cm=%d",b->id, b->cm); 
     doPost("barValue",str); 

     /* printf("\nEnding thread %ld", b->id); */ 
     changed_direction = false; 
     pthread_mutex_unlock(&bar_mutex); 
     sleep(1); 
    } 
    pthread_exit(NULL); 
} 
+1

爲了有效地進行調試,首先要做的是添加錯誤檢查和日誌記錄到***所有**相關的*函數調用(至少在這裏調用'pthread _ *()'調用)。 – alk

+0

也許最好把'sprintf(str,「id =%ld&cm =%d」,b-> id,b-> cm);'移到由'write_mutex'保護的關鍵部分? – alk

回答

0

好吧,這個問題不在這裏。該代碼真的有效。使用GDB,我看到有2個全局變量酒吧具有相同的名稱,但具有不同的引用,因爲我爲同一個變量做了2個malloc,並且我在2個不同的函數中使用了該變量,而不是僅更新了bot結構...我剛剛刪除了意想不到的malloc,一切正常。