我正在用 C 语言简单地实现一个信号量,虽然我的实现工作正常(作为二进制信号量),但我对它的有效性有疑问。
我的担忧源于我对等待函数的定义:
void Wait(int semid) {
char *shmPtr;
shmPtr = shmat(semid, NULL, 0);
if(shmPtr == (void *) -1){
printf("Could not attach to semaphore...\n");
exit(1);
}
//Wait for the value in shared memory to
//equal 0, then set it equal to 1,
//detach and return
while( (*shmPtr) != 0);
(*shmPtr) = 1;
if(shmdt(shmPtr) < 0) {
printf("Cannot detach from semaphore...");
}
return;
}
我的问题在于 while( (*shmPtr) != 0) 环形。假设我们有 2 个正在等待的进程。第三个进程将信号量的值更改为等于 0(忽略这是信号量的二进制实现这一事实)。
我担心的是,如果进程 1 评估 while 循环的条件为假,然后在将信号量值设置为等于 1 之前 CPU 上下文切换到进程 2,则两个进程都将进入临界区。
是否有更好的方法来实现等待功能?我见过很多人使用 pthread_cond_wait,但它使用的互斥体基本上违背了信号量实现的目的。
谢谢
编辑:添加维基百科在 C 中的 TestAndSet 实现以在评论中引用
#define LOCKED 1
int TestAndSet(int* lockPtr) {
int oldValue;
oldValue = *lockPtr;
*lockPtr = LOCKED;
// -- End of atomic segment --
return oldValue;
}
最佳答案
正如 Tom 评论的那样,要使信号量正确,您需要原子测试和设置或比较和交换(比较交换)。
但这还不是全部。由于您正在使用共享内存(即通过多个进程),C11 ( Link ) 提供的原子操作是不够的。
既然您无论如何都在调用 Posix 函数,我假设您可以访问 Posix 信号量。
“POSIX 信号量允许进程和线程同步它们的操作。” ( Link )
关于c - C中信号量的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54898512/