多进程 共享内存使用互斥锁(包括多线程)

整理一下之前的技术历程。其实挺简单的。我怕忘了

有个项目式多进程多线程都有的。进程之间共享数据和通信我们使用了共享内存。

而有时候要修改一些共享内存的变量,为了避免冲突(因为多线程多进程情况下 都有可能会同时访问一块数据),那应该怎么做呢?

下面附上代码和当初的尝试。

我们一开始用的互斥锁。在共享内存的结构中加入 pthread_mutex_t

#include <pthread.h>
#include <vector>
#include <utility>

struct SharedData {
    pthread_mutex_t mutex_cor; // 用于保护 coordinates 和 coordinates_size
    pthread_mutex_t mutex_df;  // 用于保护 sigAmt 的修改
    int coordinates_size;
    std::vector<std::pair<int, int>> coordinates;
    struct {
        int sigAmt[10];
    } df;
    int curChannel;
};

初始化互斥锁

SharedData* shm_data = new SharedData();
pthread_mutex_init(&shm_data->mutex_cor, nullptr); // 默认属性初始化
pthread_mutex_init(&shm_data->mutex_df, nullptr);

然后我们会修改一些数据。先解锁  然后修改数据 再解锁

pthread_mutex_lock(&shm_data->mutex_cor);

if (shm_data->coordinates_size < 4) {
    shm_data->coordinates_size++;
    std::ostringstream oss;
    for (size_t i = 0; i < bit_decode.numel(); i++) {
        oss << ((bit_decode[i] == 1.0) ? '1' : '0');
    }
    std::pair<int, int> coordinate = parseMessageType(oss.str());
    shm_data->coordinates.push_back(coordinate);
}

pthread_mutex_unlock(&shm_data->mutex_cor);

当然 这些变量 你是不需要关心的。只是我这个代码里边用到了。同时为了保密的需求我也把源代码改了改 。只是显得有这么回事罢了。

销毁互斥锁

pthread_mutex_destroy(&shm_data->mutex_cor);
pthread_mutex_destroy(&shm_data->mutex_df);
delete shm_data;

但是我发现 在多进程的情况下 是不能这么做的,会出问题的。不过课本上不是说多进程也可以用互斥锁么。当时很疑惑哦。然后为了快点干完活,我又用了信号量。当时心里有预感了,pthread是多线程的库 但是对于多进程 是不是就不能用多线程的库了呢?

因为信号量是原子操作 不care你是什么多进程多线程。

信号量就是在结构体里定义几个sem_t类型的变量

    sem_t semaphore;  // 将信号量放入共享内存
    sem_t semaphore_df;  // 将信号量放入共享内存
    sem_t semaphore_sc; //控制success的信号量

之后采用信号量处理一些互斥


    if (fd == -1)
    {
        perror("Failed to open file");
        LOG_ERROR("Failed to open the result file");
        sem_wait(&shm_data->semaphore_df);  // 等待信号量,进入临界区
        shm_data->df.errNum=0x01;
        sem_post(&shm_data->semaphore_df);  // 退出临界区
        perror("Failed to write to file");  
        return 1;
    }

可以看得出来呢,其实就是把互斥的操作夹在了sem_wait和sem_post之间。

关于信号量网上有很多教程 我不赘述了。

采用信号量之后就没啥问题了。能跑。但是用信号量还有个缺点 就是可能不如互斥锁那么快。

所以回过头来看一下pthread的互斥锁有什么问题

其实真正的问题就是多进程环境中运行时,标准的 多线程互斥锁 (pthread_mutex) 默认是 进程内线程间同步 的,无法跨进程使用。但你可以通过设置互斥锁的属性为 PTHREAD_PROCESS_SHARED,让它适用于多进程。

要在多进程间使用 pthread_mutex,需要将其属性设置为 PTHREAD_PROCESS_SHARED,这样互斥锁可以放置在共享内存中,供多个进程访问。

共享内存初始化

初始化共享内存和互斥锁:

int shm_fd = shm_open("/shared_memory", O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, sizeof(SharedData));

// 将共享内存映射到进程地址空间
SharedData* shm_data = (SharedData*)mmap(
    nullptr,
    sizeof(SharedData),
    PROT_READ | PROT_WRITE,
    MAP_SHARED,
    shm_fd,
    0
);

if (shm_data == MAP_FAILED) {
    perror("mmap failed");
    return -1;
}

// 初始化互斥锁属性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);

// 初始化互斥锁
pthread_mutex_init(&shm_data->mutex_cor, &attr);

// 销毁属性
pthread_mutexattr_destroy(&attr);

// 初始化其他共享数据
shm_data->coordinates_size = 0;
shm_data->curChannel = 1;

进程间使用互斥锁

在每个进程中,可以通过 pthread_mutex_lockpthread_mutex_unlock 对共享资源加锁:

pthread_mutex_lock(&shm_data->mutex_cor);

// 修改共享数据
if (shm_data->coordinates_size < 4) {
    shm_data->coordinates_size++;
    std::cout << "coordinates_size updated to " << shm_data->coordinates_size << std::endl;
}

pthread_mutex_unlock(&shm_data->mutex_cor);

这样就可以了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值