![](/img/trans.png)
[英]Is there a full memory barrier around sem_post(sem_t * sem) and sem_wait(sem_t * sem)?
[英]posix sem_post can't wake sem_wait where the sem init in thread. linux
这是一个奇怪的问题。我先初始化sem并对其进行销毁,然后再在线程中对其进行初始化。然后,我无法再次唤醒它。代码为:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
sem_t sem;
int key = 1;
static void *
wait_func()
{
printf("i'm wait\n");
sem_wait(&sem);
}
static void *
cancel_func(void *arg)
{
pthread_t tid = *(pthread_t *)arg;
if (key == 1)
{
sleep(1);
key = 0;
}
else
sleep(3);
if(pthread_cancel(tid) == 0)
printf("cancle!\n");
sem_init(&sem, 0, 0);
sem_destroy(&sem);
}
int
main(int argc, char *argv[])
{
pthread_t wthread, cthread;
pthread_attr_t attr;
int i = 0;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
sem_init(&sem, 0, 0);
while (i < 2)
{
// sem_init(&sem, 0, 0);
pthread_create(&wthread, &attr, wait_func, NULL);
if (i < 1)
pthread_create(&cthread, &attr, cancel_func, &wthread);
if (key == 0)
{
sleep(2);
if (sem_post(&sem) == 0)
printf("post!\n");
key = 1;
}
sleep(4);
++i;
}
sleep(1000);
}
但是,这将像在注释中那样在while循环中更改sem_init的工作!所以我建立了两个程序,并找到1)线程中的init,sem_post没有调用sys_futex,如下所示:
nanosleep({2, 0}, i'm wait
{2,0})= 0 write(1,“ post!\\ n”,6post!)= 6
2)在主进程中初始化,sem_post调用sys_futex,如下所示:
nanosleep({2, 0}, i'm wait
{2,0})= 0 futex(0x600dc0,FUTEX_WAKE_PRIVATE,1)= 1写(1,“ post!\\ n”,6post!)= 6
然后,我以为这可能是syscall的问题。我用gdb拆装了sem_post中的两个程序。 不幸的是,1)在线程中初始化,它还在sem_post中调用syscall; 2)比较了rip是syscall的注册表状态,也是如此。
in thread:
rax 0xca 202 //sys_futex
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0 //utime
rdx 0x1 1 //val
rsi 0x81 129 //op:private_wake
rdi 0x600dc0 6294976 //sem uaddr
in main process:
rax 0xca 202
rbx 0x3c0e61bbc0 257939323840
rcx 0x0 0
rdx 0x1 1
rsi 0x81 129
rdi 0x600da0 6294944
最后,我对这个问题一无所知。谢谢,请给我一些建议以找出解决方案。
我认为您的问题在于对key
的访问。 不能保证对共享变量的访问是原子的。 特别是,编译器可能会优化从内存中读取值的过程,从而不会看到在另一个线程中完成的值修改。
为了避免优化程序启动,您必须声明key
变量volatile
。 但我不知道,你已经写你的程序将保证有问题,保证线程都保证看到的修改和并行写记忆障碍的方式不混合的东西了。
现代C11还具有_Atomic
以确保访问是原子的。 但是C11尚未完全实现(可能有些编译器具有该功能)。 如果是这样,则信号量会出现问题,因为C11仅具有互斥量,而没有信号量作为锁定结构。 这两个功能如何协同工作尚未确定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.