簡體   English   中英

在C中使用線程時的奇怪行為

[英]Strange behavior when using threads in C

我對線程很陌生,很難理解下面代碼的行為。 假設我使用命令行輸入10,我希望輸出為20,因為有兩個線程將count的值遞增十次。 但是,每次我運行此程序時輸出都不是20。 以下是我的一些嘗試:

命令行輸入:10,預期輸出:20,實際輸出:15

命令行輸入:10,預期輸出:20,實際輸出:10

命令行輸入:10,預期輸出:20,實際輸出:13

命令行輸入:10,例外輸出:20,實際輸出:20

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

/* The threads will increment this count 
 * n times (command line input).
 */
int count = 0;

/* The function the threads will perform */
void *increment(void *params);


int main(int argc, char *argv[]) {

    /* Take in command line input for number of iterations */
    long iterations = (long)atoi(argv[1]);

    pthread_t thread_1, thread_2;

    /* Create two threads. */
    pthread_create(&thread_1, NULL, increment, (void*)iterations);
    pthread_create(&thread_2, NULL, increment, (void*)iterations);

    /* Wait for both to finish */
    pthread_join(thread_1, NULL);
    pthread_join(thread_2, NULL);

    /* Print the final result for count. */
    printf("Count = %d.\n", count);
    pthread_exit(NULL);

}

void *increment(void *params) {
    long iterations = (long)params;
    int i;
    /* Increment global count */
    for(i = 0; i < iterations; i++) {
        count++;
    }
    pthread_exit(NULL);
}

您的增量不是原子的,並且您沒有插入任何同步機制,因此,您的一個線程當然會覆蓋count而另一個線程仍在遞增計數,從而導致增量的“損失”。

您需要一個原子增量功能(在Windows上具有InterlockedIncrement )或顯式鎖定機制(例如互斥鎖)。

要在匯編中對兩個數字求和,通常需要以下幾個指令:

  • 將數據移至某個寄存器
  • 向該寄存器添加一些值
  • 將數據從寄存器移到內存中的某個單元

因此,當操作系統給您的程序系統時間時,它不能保證所有這些操作都不會中斷。 這些稱為關鍵部分。 每次輸入這樣的部分時,都需要同步兩個線程。

這應該工作:

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

/* The threads will increment this count 
 * n times (command line input).
 */
int count = 0;
pthread_mutex_t lock;
/* The function the threads will perform */
void *increment(void *params);


int main(int argc, char *argv[]) {

    /* Take in command line input for number of iterations */
    long iterations = (long)atoi(argv[1]);

    pthread_t thread_1, thread_2;
    pthread_mutex_init(&lock); //initialize the mutex

    /* Create two threads. */
    pthread_create(&thread_1, NULL, increment, (void*)iterations);
    pthread_create(&thread_2, NULL, increment, (void*)iterations);

    /* Wait for both to finish */
    pthread_join(thread_1, NULL);
    pthread_join(thread_2, NULL);

    /* Print the final result for count. */
    printf("Count = %d.\n", count);
    pthread_mutex_destroy(&lock); //destroy the mutex, its similar to malloc and free
    pthread_exit(NULL);

}

void *increment(void *params) {
    long iterations = (long)params;
    int i;
    int local_count = 0;
    /* Increment global count */
    for(i = 0; i < iterations; i++) {
        local_count++;
    }

   pthread_mutex_lock(&lock); //enter a critical section
   count += local_count;
   pthread_mutex_unlock(&lock); //exit a critical section
   pthread_exit(NULL);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM