синхронизация потоков с мьютексами - PullRequest
1 голос
/ 26 февраля 2010

В Qt у меня есть метод, который содержит блокировку и разблокировку мьютекса. Проблема в том, что, когда мьютекс разблокирован, иногда требуется много времени, чтобы другой поток снова получил блокировку. Другими словами, кажется, что тот же поток может вернуть блокировку (метод, вызванный в цикле), даже если другой поток ожидает его. Что я могу сделать по этому поводу? Один поток является qthread, а другой поток является основным потоком.

Ответы [ 3 ]

4 голосов
/ 26 февраля 2010

Вы можете сделать так, чтобы ваш поток, который только что разблокировал мьютекс, освободил процессор. В Posix вы делаете это, вызывая pthread_yield(), а в Windows - Sleep(0).

Тем не менее, нет никакой гарантии, что поток, ожидающий блокировки, будет запланирован до того, как ваш поток снова проснется.

0 голосов
/ 27 сентября 2012

Если вы хотите убедиться, что один поток имеет приоритет над другим, можно использовать QReadWriteLock. Он адаптирован к типичному сценарию, в котором n потоков будут считывать значение в бесконечном цикле, и только один поток будет его обновлять. Я думаю, что это сценарий, который вы описали.

QReadWriteLock предлагает два способа блокировки: lockForRead() и lockForWrite(). Потоки, зависящие от значения, будут использовать последнее, в то время как поток, обновляющий значение (обычно через графический интерфейс), будет использовать первое (lockForWrite()) и будет иметь высший приоритет. Вам не нужно будет спать или уступать или что-то еще.

Пример кода

Допустим, у вас есть QReadWrite lock; где-то.

Тема "Читатель"

forever {
    lock.lockForRead();
    if (condition) {
        do_stuff();
    }
    lock.unlock();
}

Тема "Писатель"

// external input (eg. user) changes the thread
lock.lockForWrite(); // will block as soon as the reader lock ends
update_condition();
lock.unlock();
0 голосов
/ 26 февраля 2010

Не должно быть возможности снять блокировку и затем вернуть ее, если какой-то другой поток уже ожидает ее.

Убедитесь, что вы действительно снимаете блокировку, когда думаете, что делаете. Убедитесь, что ожидающий поток действительно ждет (а не запускает цикл с помощью тестов и блокировок триллока, я действительно делал это один раз и сначала был очень озадачен :)).

Или, если ожидающий поток действительно не успевает даже достичь кода блокировки, попробуйте QThread :: yieldCurrentThread (). Это остановит текущий поток и даст планировщику возможность передать выполнение кому-то еще. Может вызвать ненужное переключение в зависимости от натяжения вашей петли.

...