如果只有一个线程使用互斥锁,跨线程的共享内存会损坏吗?

Posted

技术标签:

【中文标题】如果只有一个线程使用互斥锁,跨线程的共享内存会损坏吗?【英文标题】:Will shared memory across threads get corrupted if only one thread uses mutex? 【发布时间】:2016-03-25 14:51:37 【问题描述】:

我遇到需要跨线程访问共享内存中的变量的情况。该变量最初在许多地方的现有代码中定义并不断更新。我正在添加允许这个现有代码库作为后台线程运行的代码,但我需要从这个共享变量中读取数据。

我的问题是每次更新时是否需要在现有代码库中添加互斥锁?或者我可以在读取数据时将互斥锁添加到新代码中。我在下面创建了以下似乎可以锻炼的小测试用例。

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


typedef struct my_data 

    int shared;

MY_DATA;

MY_DATA data;
pthread_mutex_t lock;


void *background(void *x_void_ptr)

    int i = 0;
    int sleep_time;
    while(i < 10)
    

        data.shared++;

        printf("BACK thread, Data = %d\n", data.shared);

        sleep_time = rand()%5;
        sleep(sleep_time);
        i++;
    


    return NULL;



int main()



    int sleep_time;
    pthread_t bg_thread;


    if(pthread_create(&bg_thread, NULL, background, NULL)) 

        fprintf(stderr, "Error creating thread\n");
        return 1;

    

    MY_DATA *p_data = &data;

    int i = 0;
    while(i < 10)
    
        pthread_mutex_lock(&lock);
        printf("FOR thread, Data = %d\n", p_data->shared);


        pthread_mutex_unlock(&lock);
        sleep_time = rand()%5;
        sleep(sleep_time);

        i++;
    



    // Finish up
    if(pthread_join(bg_thread, NULL)) 

        fprintf(stderr, "Error joining thread\n");
        return 2;

    


    return 0;


输出:

FOR thread, Data = 0
BACK thread, Data = 1
BACK thread, Data = 2
FOR thread, Data = 2
FOR thread, Data = 2
BACK thread, Data = 3
BACK thread, Data = 4
BACK thread, Data = 5
FOR thread, Data = 5
BACK thread, Data = 6
BACK thread, Data = 7
BACK thread, Data = 8
FOR thread, Data = 8
FOR thread, Data = 8
BACK thread, Data = 9
FOR thread, Data = 9
BACK thread, Data = 10
FOR thread, Data = 10
FOR thread, Data = 10
FOR thread, Data = 10

多次运行后,看起来没有数据损坏(即前台正在读取正确的数据),但我的直觉是我需要在前台和后台代码中都有互斥锁。

【问题讨论】:

您可能需要重新阅读互斥锁的概念。 只在一个线程中使用互斥锁是没有意义的。所以要么你不需要它,要么你做错了。也许您应该查看互斥锁的用途。 请注意,进程中的所有全局内存(线程本地存储和函数中的局部变量除外)在线程之间共享。共享内存是进程之间共享内存的术语。无论内存是由线程还是进程访问,只要有多个执行线程同时访问同一个内存,您都需要确保访问得到正确管理(例如使用互斥锁)。 Mut-Ex 源自“互斥”:en.wikipedia.org/wiki/Mutual_exclusion @JonathanLeffler 感谢这个答案。我怀疑答案是我在代码的所有部分都需要它,但我试图偷懒 【参考方案1】:

将材料从我的comment 转移到答案中。

请注意,进程中的所有全局内存(线程局部存储和函数中的局部变量除外)在线程之间共享。共享内存是进程之间共享内存的一个术语。

无论内存是由线程还是进程访问,只要有多个执行线程可能同时访问同一内存,您就需要确保访问得到正确管理(例如,使用互斥锁)。如今,假设您在一台机器上只有一个内核在工作是很不安全的,因此潜在的并发访问是常态。

【讨论】:

【参考方案2】:

不,你的记忆不会被破坏,阅读对此没有任何影响。 但是你会在不一致的状态下阅读,这同样糟糕。

【讨论】:

是的,你们正在确认我的想法。就像我之前提到的那样,我试图变得懒惰并且不必大量修改这个现有的代码库,它会多次访问这个数据结构。感谢您的回复。

以上是关于如果只有一个线程使用互斥锁,跨线程的共享内存会损坏吗?的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程编程—锁优化

java多线程编程——锁优化

仅读取共享内存时的互斥锁

线程锁(互斥锁Mutex)

逸天干货丨Java 多线程编程(锁优化)

线程互斥锁