简体   繁体   English

在C中使用线程时的奇怪行为

[英]Strange behavior when using threads in C

I am quite new to threads and am having difficulty understanding the behavior of the code below. 我对线程很陌生,很难理解下面代码的行为。 Suppose I use the command line input 10, I would expect the output to be 20, since there are two threads incrementing the value of count ten times each. 假设我使用命令行输入10,我希望输出为20,因为有两个线程将count的值递增十次。 However the output is not 20 every time I run this program. 但是,每次我运行此程序时输出都不是20。 Below are some of my attempts: 以下是我的一些尝试:

Command line input: 10, Expected output: 20, Actual output: 15 命令行输入:10,预期输出:20,实际输出:15

Command line input: 10, Expected output: 20, Actual output: 10 命令行输入:10,预期输出:20,实际输出:10

Command line input: 10, Expected output: 20, Actual output: 13 命令行输入:10,预期输出:20,实际输出:13

Command line input: 10, Excepted output: 20, Actual output: 20 命令行输入: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);
}

Your increment is not atomic and you didn't insert any synchronization mechanic, so of course your one of your threads will overwrite count while the other was still incrementing it, causing "losses" of incrementations. 您的增量不是原子的,并且您没有插入任何同步机制,因此,您的一个线程当然会覆盖count而另一个线程仍在递增计数,从而导致增量的“损失”。

You need an atomic increment function (on Windows, you have InterlockedIncrement for this), or an explicit locking mechanism (like a mutex). 您需要一个原子增量功能(在Windows上具有InterlockedIncrement )或显式锁定机制(例如互斥锁)。

To sum two numbers in assembly usually requires several instructions: 要在汇编中对两个数字求和,通常需要以下几个指令:

  • move data into some register 将数据移至某个寄存器
  • add some value to that register 向该寄存器添加一些值
  • move the data from the register to some cell in the memory 将数据从寄存器移到内存中的某个单元

Thereofore, when the operating system gives your program system time, it does not guarantee that all those operations are done without any interruption. 因此,当操作系统给您的程序系统时间时,它不能保证所有这些操作都不会中断。 These are called critical sections. 这些称为关键部分。 Every time you enter such a section, you'd need to syncrhonize the two threads. 每次输入这样的部分时,都需要同步两个线程。

This should work: 这应该工作:

#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