簡體   English   中英

posix sem_post無法喚醒sem_wait,其中sem初始化在線程中。 linux

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM