簡體   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