等待函数的工作原理(关于条件变量)

Ala*_*ACK 5 c multithreading

我对条件变量的工作方式(在共享数据并发访问方面)的理解有些困惑

以下是伪C代码,以说明我当前的问题

// Thread 1: Producer
void cakeMaker()
{
    lock(some_lock);
    while(number_of_cakes == MAX_CAKES)
        wait(rack_has_space);

    number_of_cakes++;

    signal(rack_has_cakes);
    unlock(some_lock);
}

// Thread 2: Consumer
void cakeEater()
{
    lock(some_lock);
    while(number_of_cakes == 0)
        wait(rack_has_cakes);

    number_of_cakes--;

    signal(rack_has_space);
    unlock(some_lock);
}
Run Code Online (Sandbox Code Playgroud)

可以说我们目前有number_of_cakes = 0,所以Thread 2目前仍停留在此wait(rack_has_cakes)Thread 1运行并number_of_cakes以1 递增。然后它开始signal(rack_has_cakes)-唤醒Thread 2,不幸的Thread 2是在Thread 1调用之前唤醒unlock(some_lock),因此它再次回到睡眠状态,并且信号已丢失。

我对wait和的内部运作感到非常困惑signal。他们到底发生了什么?它们是否像某个布尔标志,当我们调用signal时将其自动设置为1并在等待成功时再次将其设置为0?到底是怎么回事?

有人可以让我逐步执行上述代码的第1步迭代,重点放在信号和等待期间会发生什么吗?

Sam*_*hik 5

线程2在线程1调用unlock(some_lock)之前被唤醒,因此它再次回到睡眠状态,并且信号已丢失。

不,那不是它的工作原理。我将使用C ++ std::condition_variable进行引用,但是POSIX线程以及大多数互斥锁和条件变量的常规实现都以相同的方式工作。基本概念是相同的。

当线程2开始等待条件变量时,它已锁定互斥锁。等待()操作解锁互斥量和条件变量等待原子

以原子方式释放锁,阻塞当前正在执行的线程,并将其添加到等待* this的线程列表中。

该操作被认为是“原子的”。换句话说,不可分割。

然后,当发出条件变量的信号时,线程将重新锁定互斥锁:

解除阻止后,无论出于何种原因,都将重新获得锁定并等待退出。

该线程不会在另一个线程“调用解锁”之前“返回睡眠”。如果互斥锁尚未解锁:当线程在被条件变量发出信号后唤醒时,线程将始终等待直到再次成功锁定互斥锁为止。这是无条件的。当wait()返回互斥仍处于锁定状态。然后,只有这样,wait()函数才会返回。因此,事件的顺序为:

  1. 一个线程已锁定互斥锁,将某些计数器,变量或任何类型的互斥锁保护的数据设置为另一线程正在等待的状态。这样做之后,线程会向状态变量发出信号,然后在互斥量处于闲置状态时将其解锁。

  2. 另一个线程wait()在状态变量上锁定互斥之前。其中之一wait()的先决条件是互斥之前必须锁定wait()荷兰国际集团在链接状态变量。因此,wait()操作可以“原子地”解锁互斥锁。也就是说,没有实例将互斥锁解锁,并且线程尚未在条件变量上等待。当wait()解锁互斥量,可以保证该线程将等待,它会醒来。您可以将其带到银行。

  3. 一旦条件变量发出信号时,wait()荷兰国际集团线程从返回wait(),直到它重新锁定互斥。从条件变量接收到信号只是第一步,互斥锁必须在wait()操作的最后一步中通过线程再次锁定。当然,这仅在信号线程解锁互斥锁之后才发生。

当一个线程获得由条件变量发出信号,它返回从wait()。但不是立即,它必须等到线程再次锁定互斥锁之后,无论它花费多长时间。它不会“回到睡眠状态”,而是要等待互斥锁再次锁定,然后再返回。您可以确保收到的条件变量信号将导致线程从返回wait(),并且互斥锁将被线程重新锁定。并且由于原始的先解锁后等待操作是原子操作,所以可以确保您接收到条件变量信号。

  • 不,我不认为这是错误的。您不需要有专用的互斥锁;此外,您甚至可以采用另一种方式:使用单个条件变量。条件变量的定义可以简单地是“蛋糕的数量已经改变”。在这两种情况下,您都使用条件变量来等待蛋糕数量满足特定条件。当“蛋糕数量发生变化”时,您再次检查现在是否满足此特定条件。结束。工作完成了。事实上,新的“蛋糕数量”可能不满足特定条件——没关系,你只需继续等待,直到它满足。 (2认同)