gpt4 book ai didi

c - posix sem_post 无法在线程中的 sem init 处唤醒 sem_wait。 Linux

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:39:12 26 4
gpt4 key购买 nike

这是一个奇怪的问题。我先初始化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}) = 0write(1, "post!\n", 6post!) = 6

2)在主进程中初始化,sem_post调用sys_futex,像这样:

nanosleep({2, 0}, i'm wait

{2, 0}) = 0futex(0x600dc0, FUTEX_WAKE_PRIVATE, 1) = 1write(1, "post!\n", 6post!) = 6

然后,我想这可能是系统调用的问题。我已经使用 gdb 反汇编了 sem_post 中的两个程序。不幸的是,1)线程中的init,它也在sem_post中调用了系统调用;2)比较了它们的注册状态,其中rip是系统调用,也是一样。

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 只有互斥量而不是信号量作为锁结构。目前还没有具体说明这两个功能如何合作。

关于c - posix sem_post 无法在线程中的 sem init 处唤醒 sem_wait。 Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9997655/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com