La diferencia entre std :: condition_variable notify_one () y notify_all ()

notify_one()A diferencia de lo que notify_all()se usa comúnmente para despertar un hilo bloqueado, el hilo intenta adquirir el bloqueo inmediatamente después de ser despertado.

notify_one()Debido a que solo se despierta un subproceso, no hay contención de bloqueo, por lo que el bloqueo se puede obtener de inmediato. El resto de los hilos no se despertarán y deberán esperar otra llamada notify_one()o notify_all().

notify_all()Todos los subprocesos bloqueados se despiertan, hay contención de bloqueo y solo un subproceso puede adquirir el bloqueo. ¿Qué sucede con los subprocesos restantes que no han adquirido el bloqueo? ¿Bloqueará? ¿O seguir intentando obtener el candado? La respuesta es seguir intentando adquirir el bloqueo (similar al sondeo) sin volver a bloquear. Cuando el hilo que sujeta el candado libera el candado, uno de estos hilos adquiere el candado. El resto intentará adquirir la cerradura.

Mira el siguiente ejemplo:

// condition_variable example
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    
    
	std::unique_lock<std::mutex> lck(mtx);
	while (!ready) cv.wait(lck);
	// ...
	std::cout << "thread " << id << '\n';
}

void go() {
    
    
	std::unique_lock<std::mutex> lck(mtx);
	ready = true;
	cv.notify_all(); // 这是重点
}

int main()
{
    
    
	std::thread threads[10];
	// spawn 10 threads:
	for (int i = 0; i < 10; ++i)
		threads[i] = std::thread(print_id, i);

	std::cout << "10 threads ready to race...\n";
	go();                       // go!

	for (auto& th : threads) th.join();

	return 0;
}

Los resultados de la operación son:

10 threads ready to race...
thread 2
thread 0
thread 9
thread 4
thread 6
thread 8
thread 7
thread 5
thread 3
thread 1

La salida muestra que todos los subprocesos se despertaron y luego aún adquirieron el bloqueo.

Si go()el cv.notify_all()cambio cv.notify_one(), los resultados son:

10 threads ready to race...
thread 0

La salida indica que solo se despierta un hilo y luego el hilo libera el bloqueo. En este momento, el bloqueo se ha procesado en el estado desbloqueado, pero los hilos restantes todavía están en el estado bloqueado.

Por lo tanto, cuando el hilo está bloqueado condition_variable, espera notify_one()o se notify_all()despierta, en lugar de esperar a que el bloqueo se bloquee para activarse.
Después de que se despierte el hilo, obtendrá el bloqueo mediante sondeo, y el estado de ejecución se procesará hasta que se obtenga el bloqueo, y no se bloqueará nuevamente.

Supongo que te gusta

Origin blog.csdn.net/xp178171640/article/details/106016141
Recomendado
Clasificación