简体   繁体   English

与线程同步混淆[pthreads]

[英]Confusion with thread synchronization [pthreads]

I have had a problem threads for a long time. 我有一个问题线程很长时间了。 This code is supposed to have a worker thread increment the value of a shared integer while the main thread prints it out. 假定该代码使工作线程将共享整数的值递增,而主线程将其打印出来。 However, I am not getting my expected output. 但是,我没有得到预期的输出。

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

pthread_mutex_t lock;
int shared_data = 0; //shared data


// Often shared data is more complex than just an int.
void* thread_function(void* arg)
{
    int i;
    for (i = 0; i < 10; ++i)
    {
        // Access the shared data here.
        pthread_mutex_lock(&lock);
        shared_data++;
        pthread_mutex_unlock(&lock);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int i;
    void* exit_status;
    // Initialize the mutex before trying to use it.
    pthread_mutex_init(&lock, NULL);
    pthread_create(&thread, NULL, thread_function, NULL);
    // Try to use the shared data.
    for (i = 0; i < 10; ++i)
    {
        sleep(1);
        pthread_mutex_lock(&lock);
        printf ("\r for i= %d Shared integer 's value = %d\n", i, shared_data);
        pthread_mutex_unlock(&lock);
    }
    printf("\n");
    pthread_join(thread, &exit_status);
    // Clean up the mutex when we are finished with it.
    pthread_mutex_destroy(&lock);

    return 0;
}

Here is what I expect: 这是我的期望:

for i=0 Shared Integer 's value = 0
for i=1 Shared Integer 's value = 1 
for i=3 Shared Integer 's value = 2
...
for i=10 Shared Integer 's value =10

but the result is: 但结果是:

for i=0 Shared Integer 's value = 0
for i=1 Shared Integer 's value = 10
for i=3 Shared Integer 's value = 10
...
for i=10 Shared Integer 's value =10

so how can i resoleve this? 所以我怎么能忍受这个呢?

The main thread and your worker thread are running concurrently. 主线程和工作线程正在同时运行。 That is, getting those for loops to coincide with each other perfectly is nearly impossible without extra synchronization. 也就是说,没有额外的同步,几乎不可能使这些for循环彼此完全重合。

Your output is exactly what you should expect. 您的输出正是您所期望的。 The time taken to spawn the thread allows the main thread to print before the other thread changes the shared data. 产生线程所花费的时间使主线程可以在其他线程更改共享数据之前进行打印。 Then, the print takes so long that the other thread completely finishes with its loop and increments the shared data to 10 before the main thread can get to its second iteration. 然后,打印花费了很长时间,以至于另一个线程完全完成其循环,并在主线程可以进行第二次迭代之前将共享数据增加到10。

In a perfect world, this little hack using condition variables will get you what you want: EDIT: condition variables were a bad idea for this. 在理想世界中,使用条件变量的小技巧可以为您提供所需的信息: 编辑:条件变量对此不是一个好主意。 Here is working version that uses pseudo atomic variables and doesn't contain UB :) : 这是使用伪原子变量且不包含UB :)的工作版本

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

pthread_mutex_t want_incr_mut;
pthread_mutex_t done_incr_mut;
int want_incr = 0;
int done_incr = 0;
int shared_data = 0; //shared data

// Not using atomics, so...

void wait_for_want_increment()
{
    while (1)
    {
        pthread_mutex_lock(&want_incr_mut);
        if (want_incr)
        {
            pthread_mutex_unlock(&want_incr_mut);
            return;
        }
        pthread_mutex_unlock(&want_incr_mut);
    }
}

void wait_for_done_incrementing()
{
    while (1)
    {
        pthread_mutex_lock(&done_incr_mut);
        if (done_incr)
        {
            pthread_mutex_unlock(&done_incr_mut);
            return;
        }
        pthread_mutex_unlock(&done_incr_mut);
    }
}


void done_incrementing()
{
    pthread_mutex_lock(&done_incr_mut);

    done_incr = 1;
    pthread_mutex_lock(&want_incr_mut);
    want_incr = 0;
    pthread_mutex_unlock(&want_incr_mut);

    pthread_mutex_unlock(&done_incr_mut);
}

void want_increment()
{
    pthread_mutex_lock(&want_incr_mut);

    want_incr = 1;
    pthread_mutex_lock(&done_incr_mut);
    done_incr = 0;
    pthread_mutex_unlock(&done_incr_mut);

    pthread_mutex_unlock(&want_incr_mut);
}

// Often shared data is more complex than just an int.
void* thread_function(void* arg)
{
    int i;
    for (i = 0; i < 10; ++i)
    {
        wait_for_want_increment();
        // Access the shared data here.
        shared_data++;
        done_incrementing();
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int i;
    void* exit_status;

    // Initialize the mutex before trying to use it.
    pthread_mutex_init(&want_incr_mut, NULL);
    pthread_mutex_init(&done_incr_mut, NULL);
    pthread_create(&thread, NULL, thread_function, NULL);

    // Try to use the shared data.
    for (i = 0; i <= 10; ++i)
    {
        printf("\r for i= %d Shared integer 's value = %d\n", i, shared_data);
        if (i == 10) break;

        want_increment();
        wait_for_done_incrementing();
    }
    printf("\n");
    pthread_join(thread, &exit_status);
    // Clean up the mutexes when we are finished with them.
    pthread_mutex_destroy(&want_incr_mut);
    pthread_mutex_destroy(&done_incr_mut);

    return 0;
}

Here, we just tell the worker that we want an increment and wait for him to say he is done before we continue. 在这里,我们只是告诉工人我们要增加工资,然后等他说完了再继续。 Meanwhile, the worker waits for us to want an increment and tells us when he is done. 同时,工人等待我们增加工资,并告诉我们什么时候完成。

I also changed the main loop to go to ten because that is what I think you want. 我也将主循环更改为10,因为这是我认为您想要的。

Here is my output: 这是我的输出:

for i= 0 Shared integer 's value = 0
for i= 1 Shared integer 's value = 1
for i= 2 Shared integer 's value = 2
for i= 3 Shared integer 's value = 3
for i= 4 Shared integer 's value = 4
for i= 5 Shared integer 's value = 5
for i= 6 Shared integer 's value = 6
for i= 7 Shared integer 's value = 7
for i= 8 Shared integer 's value = 8
for i= 9 Shared integer 's value = 9
for i= 10 Shared integer 's value = 10

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

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