使用 pthread_cond_wait 和 pthread_cond_signal 保证屈服

发布于 2024-07-30 04:43:17 字数 546 浏览 13 评论 0原文

假设我有一个带有 3 个 POSIX 线程的 C 程序,共享一个全局变量、互斥体和条件变量,其中两个正在执行以下伪代码:

...process data...
pthread_mutex_lock( &mutex );
variable = data_ptr;
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );

第三个正在运行:

while(1) {
    while( variable == NULL ) {
        pthread_mutex_wait( &cond, &mutex );
    }
    printf( "Data is %d", *variable );
}

可以安全地假设第三个线程将看到来自前两个分别是?

换句话说,如果一个线程正在等待互斥锁和条件变量,那么可以安全地假设它是下一个获得锁的线程(如果它收到信号),而不是其他可能正在等待互斥锁和条件变量的线程。锁?

Assuming I have a C program with 3 POSIX threads, sharing a global variable, mutex, and condition variable, two of which are executing the following psuedocode:

...process data...
pthread_mutex_lock( &mutex );
variable = data_ptr;
pthread_cond_signal( &cond );
pthread_mutex_unlock( &mutex );

And the third running:

while(1) {
    while( variable == NULL ) {
        pthread_mutex_wait( &cond, &mutex );
    }
    printf( "Data is %d", *variable );
}

Is it safe to assume that the third thread will see the data from each of the first two?

Put a different way, if a thread is wating on a mutex and a condition variable, is it safe to assume that it will be the next one to get the lock if it is signaled, rather than some other thread that may be waiting on the lock?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

咆哮 2024-08-06 04:43:18

根据 pthread_cond_wait 联机帮助页

未阻塞的线程应根据调度策略(如果适用)争夺互斥锁,就好像每个线程都调用了 pthread_mutex_lock()。

不幸的是,据我所知,没有可用的调度策略可以为您提供所需的行为。

According to the pthread_cond_wait manpage

The thread(s) that are unblocked shall contend for the mutex according to the scheduling policy (if applicable), and as if each had called pthread_mutex_lock().

Unfortunately as far as I can tell, there is no available scheduling policy that gives you the behavior you want.

感性 2024-08-06 04:43:17

以下是我在标准中找到的内容:

4.13调度策略

调度策略会影响进程或线程的顺序:

[...]

  • 当进程或线程从阻塞线程变为可运行线程时

一致的实现应定义每个调度策略可以修改优先级或以其他方式影响上面列出的每次发生时的进程或线程的顺序的方式。 此外,一致的实现应定义在什么其他情况下以及以什么方式每个调度策略可以修改优先级或影响进程或线程的顺序。

所以它显然是未定义的。 这并不奇怪:一般来说,您不能假设任何有关哪个可运行线程将被安排运行的信息。

Here is what I found in the standard:

4.13 Scheduling Policy

A scheduling policy affects process or thread ordering:

[...]

  • When a process or thread is a blocked thread and it becomes a runnable thread

Conforming implementations shall define the manner in which each of the scheduling policies may modify the priorities or otherwise affect the ordering of processes or threads at each of the occurrences listed above. Additionally, conforming implementations shall define in what other circumstances and in what manner each scheduling policy may modify the priorities or affect the ordering of processes or threads.

So it's apparently undefined. It's not surprising: generally speaking, you can't assume anything about which runnable thread will be scheduled to run.

梨涡少年 2024-08-06 04:43:17

不存在 pthread_mutex_wait 这样的东西。 我假设您的意思是:

pthread_mutex_lock(&mutex);
/* ... */
while (1) {
  while (variable == NULL)
    pthread_cond_wait(&cond, &mutex);
  printf("Data is %d", *variable);
}
/* ... */
pthread_mutex_unlock(&mutex);

无法保证第三个线程会看到来自两个线程的数据。 pthread_cond_signal 将唤醒第三个线程,但它可能不会立即获取互斥锁。 其他写入者之一可能会首先获取互斥体。 然而,您可以通过更多的工作来实现您想要的:

void put(int *p) {
  pthread_mutex_lock(&mutex);
  while (variable)
    pthread_cond_wait(&cond_empty, &mutex);
  variable = p;
  pthread_cond_signal(&cond_full);
  pthread_mutex_unlock(&mutex);
}

int *get() {
  int *ret;

  pthread_mutex_lock(&mutex);
  while (!variable)
    pthread_cond_wait(&cond_full, &mutex);
  ret = variable;
  variable = NULL;
  pthread_cond_signal(&cond_empty);
  pthread_mutex_unlock(&mutex);

  return ret;
}

通过显式等待读取变量,我们避免了潜在的竞争条件。

There's no such thing as pthread_mutex_wait. I assume you mean:

pthread_mutex_lock(&mutex);
/* ... */
while (1) {
  while (variable == NULL)
    pthread_cond_wait(&cond, &mutex);
  printf("Data is %d", *variable);
}
/* ... */
pthread_mutex_unlock(&mutex);

There is no guarentee that the third thread will see the data from both. pthread_cond_signal will awaken the third thread, but it may not take the mutex immediately. One of the other writers may take the mutex first. However you can acheive what you want with a bit more work:

void put(int *p) {
  pthread_mutex_lock(&mutex);
  while (variable)
    pthread_cond_wait(&cond_empty, &mutex);
  variable = p;
  pthread_cond_signal(&cond_full);
  pthread_mutex_unlock(&mutex);
}

int *get() {
  int *ret;

  pthread_mutex_lock(&mutex);
  while (!variable)
    pthread_cond_wait(&cond_full, &mutex);
  ret = variable;
  variable = NULL;
  pthread_cond_signal(&cond_empty);
  pthread_mutex_unlock(&mutex);

  return ret;
}

By explicitly waiting for the variable to be read, we avoid the potential race condition.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文