Многопоточность, когда уступать сну - PullRequest
12 голосов
/ 19 апреля 2010

Чтобы уточнить терминологию, доходность - это когда поток отдает свой временной интервал. Моя интересная платформа - потоки POSIX, но я думаю, что вопрос общий.

Предположим, у меня есть шаблон потребитель / производитель. Если я хочу задушить или потребителя или производителя, что лучше использовать, спать или приносить доход? Меня больше всего интересует эффективность использования обеих функций.

Ответы [ 4 ]

10 голосов
/ 19 апреля 2010

сон и урожайность не совпадают. При вызове sleep процесс / поток передает CPU другому процессу / потоку на заданное количество времени.

yield уступает ЦП другому потоку, но может немедленно вернуться, если нет других потоков, ожидающих ЦП.

Так что, если вы хотите регулировать скорость, например, при потоковой передаче данных через регулярные промежутки времени, то функции сна или наносна - это используемые функции.

Если необходима синхронизация между производителем / потребителем, вам следует использовать мьютекс / условное ожидание.

10 голосов
/ 19 апреля 2010

«Правильный» способ кодирования производителя / потребителя состоит в том, чтобы потребитель ожидал данных производителя. Вы можете достичь этого с помощью объекта синхронизации, такого как Mutex. Потребитель будет Wait на мьютексе, который блокирует его выполнение до тех пор, пока данные не станут доступны. В свою очередь, производитель сообщит мьютекс, когда данные будут доступны, что разбудит поток потребителя, чтобы он мог начать обработку. Это более эффективно, чем sleep с точки зрения обоих:

  • загрузка ЦП (циклы не тратятся впустую) и
  • Время выполнения (выполнение начинается, как только становятся доступными данные, а не когда запланирован запуск потока).

Тем не менее, вот анализ доходности против сна, который вы просили. Вам может понадобиться использовать такую ​​схему, если по какой-то причине ожидание вывода невозможно:

Это зависит от того, сколько трафика вы получаете - если данные постоянно принимаются и обрабатываются, вы можете рассмотреть возможность получения дохода. Однако в большинстве случаев это приведет к «занятому» циклу, который тратит большую часть своего времени без необходимости пробуждать поток, чтобы проверить, готово ли что-нибудь.

Вы, вероятно, захотите либо поспать в течение короткого периода времени (возможно, менее секунды, используя usleep), ИЛИ даже лучше использовать объект синхронизации, такой как мьютекс, чтобы сообщить о доступности данных.

1 голос
/ 19 апреля 2010

Одна из причин, по которой стоит спать, а не урожайность, - это слишком сильное раздор в конкретном критическом разделе. Допустим, например, что вы пытаетесь приобрести два замка, и на обоих замках много споров. Здесь вы можете использовать сон для экспоненциального отступления. Это позволило бы каждой неудачной попытке псевдослучайно откатиться назад, чтобы позволить другому потоку добиться успеха.

Уступка в этой ситуации не очень помогает, поскольку вероятность случайного отступления может увеличить вероятность того, что голодание нити не произойдет.

Редактировать: Хотя я знаю, что это не обязательно для Java. Реализация Java Thread.sleep(0) имеет тот же эффект, что и Thread.yield(). В этот момент это скорее вопрос стиля.

0 голосов
/ 06 июля 2011

В java некоторые реализации JVM обрабатывают Thread.yield () как no-op, то есть это может не иметь никакого эффекта. Вызов Thread.sleep () не обязательно означает, что планировщик должен уступать ЦП другому потоку; это также зависит от реализации. Он может переключаться по контексту на другой поток, который ожидает, или нет, чтобы амортизировать стоимость, связанную с переключением контекста.

...