整理一下之前的技术历程。其实挺简单的。我怕忘了
有个项目式多进程多线程都有的。进程之间共享数据和通信我们使用了共享内存。
而有时候要修改一些共享内存的变量,为了避免冲突(因为多线程多进程情况下 都有可能会同时访问一块数据),那应该怎么做呢?
下面附上代码和当初的尝试。
我们一开始用的互斥锁。在共享内存的结构中加入 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_lock 和 pthread_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);
这样就可以了。
743

被折叠的 条评论
为什么被折叠?



