简体   繁体   English

并发:使用pthread_mutex来雾化增量操作

[英]Concurrency: Using pthread_mutex to atomize an increment operation

I'm currently reading Operating Systems: Three Easy Pieces and I'm starting to get the logic behind concurrency. 我正在阅读操作系统:三个简单的部分 ,我开始得到并发的逻辑。 In the 26 "chapter" we get this example of threads and the problems around atomicity: 在26“章节”中,我们得到了线程的例子和原子性的问题:

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

static volatile int counter = 0;

// mythread()
// Simply adds 1 to counter repeatedly, in a loop
// No, this is not how you would add 10,000,000 to
// a counter, but it shows the problem nicely.

void *mythread(void *arg){
    printf("%s: begin\n", (char *) arg);
    int i;
    for (i = 0; i < 1e7; i++) {
        counter = counter + 1;
    }
    printf("%s: done\n", (char *) arg);
    return NULL;
}


// main()
// Just launches two threads (pthread_create)
// and then waits for them (pthread_join)

int main(int argc, char *argv[]) {
    pthread_t p1, p2;
    printf("main: begin (counter = %d)\n", counter);
    pthread_create(&p1, NULL, mythread, "A");
    pthread_create(&p2, NULL, mythread, "B");

    // join waits for the threads to finish
    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
    printf("main: done with both (counter = %d)\n", counter);
    return 0;

}

And it shows us the issue is that because of the race condition in the increment the value of the sum varies and rarely is the supposed. 它告诉我们的问题是,由于增量中的竞争条件,总和的价值变化而且很少是假定的。

Per example, after compilling: 每个例子,在完成后:

gcc -g -o main page6.c -Wall -pthread

and running twice I get: 并运行两次我得到:

main: begin (counter = 0)
A: begin
B: begin
A: done
B: done
main: done with both (counter = 10263001)

and: 和:

main: begin (counter = 0)
A: begin
B: begin
A: done
B: done
main: done with both (counter = 10600399)

So after reading about mutex I tried this little change to the code in the mythread() function. 所以在阅读了有关互斥锁之后,我尝试对mythread()函数中的代码进行了一些小改动。

void *mythread(void *arg){
    pthread_mutex_t lock;
    int rc = pthread_mutex_init(&lock,NULL);
    assert(rc==0); //always check sucess

    printf("%s: begin\n", (char *) arg);
    int i;

    for (i = 0; i < 1e7; i++) {
        pthread_mutex_lock(&lock);
        counter = counter + 1;
        pthread_mutex_unlock(&lock);
    }

    printf("%s: done\n", (char *) arg);
    return NULL;
}

and after compiling (in the same way) and running, it does take noticeably more time (1-2 seconds). 在编译(以相同的方式)和运行之后,它确实需要更多的时间(1-2秒)。

But the results aren't any better: 但结果并没有更好:

main: begin (counter = 0)
A: begin
B: begin
B: done
A: done
main: done with both (counter = 10019830)

and: 和:

main: begin (counter = 0)
A: begin
B: begin
B: done
A: done
main: done with both (counter = 10008806)

So why doesn't this work? 那么为什么这不起作用呢? Shouldn't this create a critical section in code? 这不应该在代码中创建一个关键部分吗? Am I missing something obvious? 我错过了一些明显的东西吗

You shouldn't have the mutex as a local variable in mythread since each thread then gets it's own copy. 您不应该将互斥锁作为mythread的局部变量,因为每个线程都会获得它自己的副本。 Make it global and initialize it in main. 使其成为全局并在main中初始化它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM