繁体   English   中英

与线程同步混淆[pthreads]

[英]Confusion with thread synchronization [pthreads]

我有一个问题线程很长时间了。 假定该代码使工作线程将共享整数的值递增,而主线程将其打印出来。 但是,我没有得到预期的输出。

#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;
}

这是我的期望:

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

但结果是:

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

所以我怎么能忍受这个呢?

主线程和工作线程正在同时运行。 也就是说,没有额外的同步,几乎不可能使这些for循环彼此完全重合。

您的输出正是您所期望的。 产生线程所花费的时间使主线程可以在其他线程更改共享数据之前进行打印。 然后,打印花费了很长时间,以至于另一个线程完全完成其循环,并在主线程可以进行第二次迭代之前将共享数据增加到10。

在理想世界中,使用条件变量的小技巧可以为您提供所需的信息: 编辑:条件变量对此不是一个好主意。 这是使用伪原子变量且不包含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;
}

在这里,我们只是告诉工人我们要增加工资,然后等他说完了再继续。 同时,工人等待我们增加工资,并告诉我们什么时候完成。

我也将主循环更改为10,因为这是我认为您想要的。

这是我的输出:

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