首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在线程中sem初始化的地方,posix sem_post无法唤醒sem_wait。linux

在线程中sem初始化的地方,posix sem_post无法唤醒sem_wait。linux
EN

Stack Overflow用户
提问于 2012-04-04 00:38:12
回答 1查看 2.8K关注 0票数 1

这是一个奇怪的问题。我先初始化sem并销毁它,然后在thread.then中再次初始化它,我不能唤醒它again.the代码是:

代码语言:javascript
复制
#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,如下所示:

代码语言:javascript
复制
nanosleep({2, 0}, i'm wait

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

2)在主进程中初始化,sem_post调用sys_futex,如下:

代码语言:javascript
复制
nanosleep({2, 0}, i'm wait

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

然后,我想这可能是syscall.I的问题,我用gdb在sem_post中反汇编了两个程序。不幸的是,1)在线程中初始化,在sem_post;2中也调用syscall )比较了它们的注册表状态,其中rip是syscall,也是一样的。

代码语言:javascript
复制
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

最后,我对这个problem.Please一无所知,请给我一些建议来找出解决方案,谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-04-04 03:51:16

我认为你的问题出在访问key上。不能保证对共享变量的访问是原子的。具体地说,编译器可能会优化从内存中读取一个值,这样它就看不到在另一个线程中完成的值的修改。

为了避免优化器介入,您必须声明key变量volatile。但我不确定您编写程序的方式是否能保证存在内存屏障,从而保证线程可以看到修改,并确保并发写入不会混淆。

现代C11也有_Atomic来确保访问是原子的。但是C11还没有完全实现(可能有一些编译器具有该功能)。如果是这样的话,信号量就有问题了,因为C11只有互斥锁而没有信号量作为锁结构。这两个功能将如何合作,目前还没有具体说明。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9997655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档