LINUX.ORG.RU

Мьютекс, голодание потока

 ,


0

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

mutex m;

void t2()
{
    while(true)
    {
        lock_guard<mutex> l(m);
        this_thread::sleep_for(10ms);
    }
}

int main()
{
    thread tr1(t2);
    this_thread::sleep_for(100ms);
    lock_guard<mutex> l(m);
    cout << "++++++++++++" << endl;
    tr1.join();
}

Я удивлён - плюсики выскакивают секунд через 17, main поток конкретно голодает. А если паузу в t2 сделать == секунде, то дождаться плюсиков нереально. Сижу и думаю - кривые какие-то мьютексы, в некоторых ситуациях можно очень больно наступить на грабли.

★★

у тебя в потоке мютекс залочен 99.99% времени.

dib2 ★★★★★
()

А ты какого поведения ожидал?

anonymous
()

Странно, что вас ничего не удивляет. t2 делает примерно 17000 захватов мьютекса, а main лишь 1. Видимо, у спящего потока приоритет ниже. Но это всё не то поведение, которое я ожидал. Пускай было бы соотношение 10 к 1, приемлемо, но не 17000.

pavlick ★★
() автор топика

Картина сильно зависит от того, как раскидать потоки по ядрам процессора. А вообще, mutex никаких гарантий на эту тему не даёт. Или пиши свой лок с нужными тебе свойствами (ticket lock?), или переделывай алгоритм, использующий мутексы, чтобы ему не плохело по таким поводам.

const86 ★★★★★
()

Мьютекс заточен на скорость работы, а не на честность. Если хочется честности — нужен свой планировщик, хоть на тех же мьютексах и conditional_variable.

vzzo ★★★
()
Ответ на: комментарий от MKuznetsov

Помогает, спасибо. Но такая несправедливость в «голом» варианте стала для меня неожиданностью.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

Но такая несправедливость в «голом» варианте стала для меня неожиданностью.

Очевидно это зависит от конкретной платформы. Под линуксом, например, std::mutex, да и вообще треды, реализованы на pthreads. Соот-но имеют аналогичное поведение.

anonymous
()
Ответ на: комментарий от pavlick

Но такая несправедливость в «голом» варианте стала для меня неожиданностью.

В разработке сложных приложений на голых потоках и примитивах синхронизации уровня mutex-а будет еще очень и очень много сюрпризов ;)

eao197 ★★★★★
()
Ответ на: комментарий от pavlick

такая несправедливость в «голом» варианте стала для меня неожиданностью

посмотри objdump -d , чтобы таких неожиданностей больше небыло.

У тебя между unlock и следующим lock всего одна инструкция, да и та jmp. Вот main поток и ждёт когда свершится чудо и шедулер переключит контекст t2 именно на ней. А учитывая, что перед jmp вообще был sleep и t2 только-только получил свой квант то спасает только отсутствие прочих вычислений в t2, если например внутри цикла while перед sleep что-нить упорно считать, то ресурс не освободится никогда.

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

Теперь принцип работы понял. Думал что мьютексы реализованы более хитро, учитывается продолжительность голодания. А оно всё топорно. Может и не плохо в целом, производительность и всё такое, но в справочниках на этом не акцентируют внимание, понял это далеко не сразу.

pavlick ★★
() автор топика

Благодарю всех за участие.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

ЕМНИП мутексы в посикс тредах работают «честно» не потому что чего то там учитывают продолжительность, а того что при попытке захватить мутекс, тред попадает в «очередь», и продвигается по ней по мере отпускания мутекса теми кто впереди. Таким образом все получается честно без всякого хитрого скедулинга. А то что получается у тебя, это больше похоже на поведение обычного спинлока.

Поправьте меня если ошибаюсь.

redixin ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.