0

我有一个 futex 的示例代码。但我无法理解代码流......

#include <stdio.h>
#include <pthread.h>
#include <linux/futex.h>
#include <syscall.h>
#include <unistd.h>

#define NUM 50

int futex_addr;

int futex_wait(void* addr, int val1){
  return syscall(SYS_futex,&futex_addr,val1, NULL, NULL, 0);
}
int futex_wake(void* addr, int n){
  return syscall(SYS_futex, addr, FUTEX_WAKE, n, NULL, NULL, 0);
}

void* thread_f(void* par){
        int id = (int) par;

    /*go to sleep*/
    futex_addr = 0;
    futex_wait(&futex_addr,0);

        printf("Thread %d starting to work!\n",id);
        return NULL;
}

int main(){
        pthread_t threads[NUM];
        int i;

        for (i=0;i<NUM;i++){
                pthread_create(&threads[i],NULL,thread_f,(void *)i);
        }

        printf("Everyone wait...\n");
        sleep(1);
        printf("Now go!\n");
    /*wake threads*/
    futex_wake(&futex_addr,50);

    /*give the threads time to complete their tasks*/
        sleep(1);


    printf("Main is quitting...\n");
        return 0;
}

输出是这样的:

Everyone wait...
Now go!
Thread 0 starting to work!
Thread 1 starting to work!
Thread 2 starting to work!
Thread 3 starting to work!
Thread 4 starting to work!
Thread 5 starting to work!
Thread 6 starting to work!
Thread 7 starting to work
Thread 8 starting to work!
Thread 9 starting to work!
.
.
Main is quitting

这段代码实际上是如何表现的?

thread_f 函数的触发器是什么?

等待和唤醒在这里如何工作?

4

1 回答 1

3
  1. 您创建 50 个线程并让主线程进入睡眠状态。
  2. 在每个线程中,您将 的值设置futex_addr为零(冗余)。
  3. futex_wait使用该值的地址和零值参数调用。这意味着“阻止,如果我指向的值(仍然)真的为零”
  4. sys_futex检查 at 的值&futex_addr是否真的为零,这是阻塞线程的条件(这对于系统调用的正确可操作性很重要,否则在 Windows 下futex_wake将不得不阻塞)。NtReleaseKeyedEvent当然,该值为零,这是任何线程曾经写入过的所有内容,因此您的线程会阻塞。
  5. 主线程最终返回sleep并使用参数 50 进行调用futex_wake,这意味着“唤醒(最多)50 个正在等待的线程&futex_addr。所以你所有的 50 个线程在一大群雷鸣般的人群中醒来。
  6. 每个线程写入一条消息stdout(没有同步,因此您可能会看到乱码输出)并退出。
  7. 主线程也退出了,没有加入线程或同步,但是由于第二次调用sleep,它很可能会“正常工作”而不会发生任何邪恶的事情(并不是说写这样的代码是一件好事!) .

请注意,这种唤醒N线程的方法有效,但不鼓励使用(就像futex最初也不鼓励使用一样)。通常,您只想唤醒一个线程(使用1)或所有线程(使用INT_MAX)。

于 2014-06-30T13:34:34.813 回答