Patrząc zsynchronizować dwa wątki o zmiennej warunku i stworzył prosty przykład do ćwiczenia.

Myślę, że pomieszałem coś podczas wykonywania synchronizacji, ponieważ konsument zawiesza się na czekanie na sygnale z CV.

Mimo że jest cv.notify_one(), jakoś linia return counter != 0 wewnątrz lambda nigdy nie jest wyzwalana i całkowicie nie rozumiem dlaczego.

#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
using namespace std::chrono_literals;

int main(int, char**)
{
    std::mutex mx;
    std::condition_variable cv;
    int counter;

    std::thread producer( [ & ] ( )
    {
        while( true )
        {
            std::lock_guard<std::mutex> lock( mx );

            std::cout << "adding task" << std::endl;
            std::this_thread::sleep_for(1s);
            ++counter;

            cv.notify_one();
        }
    });

    std::thread consumer( [ & ] ( )
    {
        while( true )
        {
            std::unique_lock<std::mutex> lock( mx );

            cv.wait( lock, [ & ] ( )
            {
                return counter > 0;
            });

            std::cout << "Executing" << std::endl;
            std::this_thread::sleep_for(.5s);
            --counter;
        }
    });

    consumer.join();
    producer.join();

    return 0;
}
0
Bebe Carabina 9 październik 2020, 20:51

1 odpowiedź

Najlepsza odpowiedź

Problemem jest wyraźnie uczciwość, jak wykazano, dodając linię jak

std::this_thread::sleep_for(0.01s);

Tuż przed tym, jak producent nabywa mutex.

Większość systemów operacyjnych nie da Ci żadnej uczciwej gwarancji na Mutexes.

Istnieje wiele sposobów pracy w kwestii sprawiedliwości. Jeśli wiesz, jak to sobie z tym poradzić, możesz zatrzymać się tutaj.

W twoim przypadku, zakładając, że twoi producenci i konsumenci nie zajmują pół sekundy lub więcej, aby umieścić pracę w kolejce , a producent nie ma nieskończonej ilości miejsc pracy , wtedy nie musisz się tym martwić. Jeśli system operacyjny sprzyja producentom nad konsumentami w chwili wysokiej konwencji, kolejka po prostu wypełnia się (lub wszystkie oczekujące zadania ostatecznie dostanie się do kolejki), zmuszając producentów, aby czekać, zwolnić Mutex i pozwolić konsumentom ich obrotu.

Należy pamiętać, że w scenariuszu producenta / konsumenta z maksymalnym rozmiarem kolejki w rzeczywistości potrzebujesz dwóch zmiennych warunku - dla warunków i Puste .

2
elbrunovsky 9 październik 2020, 18:15