Когда и зачем использовать MVar вместо TVar

Я считаю, что с TVar довольно легко работать, хотя MVar выглядит немного проще, а TVar немного более функционален.

Итак, мой вопрос довольно прост: в каком состоянии я хочу перейти на MVar, а не на TVar? Я полагаю, что в любое время, когда мне не нужно обновление транзакций, я могу использовать MVar, но какая мне от этого польза?


person Jimmy Hoffa    schedule 15.03.2013    source источник


Ответы (2)


TVars безопаснее, но медленнее.

MVars могут зайти в тупик, но они намного эффективнее.

Еще более эффективными являются IORef и atomicModifyIORef (CAS), но они сильно ограничены в том, что вы можете с ними делать.

Это действительно компромисс между безопасностью и производительностью. TVars полностью общие, очень безопасные. Все остальное в меньшей степени, по убывающей шкале.

person Don Stewart    schedule 15.03.2013
comment
Эффективность, хороший нюх. Я полагал, что они одинаково производительны, так что мораль этой истории: используйте TVar, если вам нужно обновление транзакций, в противном случае используйте MVar, потому что это значительно меньше замедлит работу вашего многопоточного приложения - person Jimmy Hoffa; 15.03.2013
comment
Кто-нибудь может посчитать реальную разницу в скорости? (По-видимому, это сложно измерить, поскольку это зависит от фактического взаимодействия потоков...) - person MathematicalOrchid; 16.03.2013
comment
@MathematicalOrchid игнорирует проблемы параллелизма: чтение и запись IORef будут вашими самыми быстрыми операциями, но GHC 7.8 поставляется с некоторыми улучшениями MVar, которые делают takeMVar/putMVar в пределах нескольких нс от read/writeIORef (скажем, 9,7/4,6 против 3,7/7/3 на моем машина (‹обычная оговорка о лжи и бенчмарках здесь›)) и у нас также есть новый очень быстрый readMVar (когда MVar заполнен, конечно). - person jberryman; 28.05.2014
comment
Также atomicModifyIORef по какой-то причине очень плохо работает в условиях конкуренции. - person jberryman; 28.05.2014
comment
@MathematicalOrchid Однажды я пытался сравнить TVars и modifyIORef. Я сделал кое-что с банковским счетом, где каждый поток выполнял транзакции между двумя банковскими счетами. Реализация IORef, очевидно, приведет к несоответствиям. В моей первой попытке удалось протестировать генератор случайных чисел, а во второй — более быстрый генератор случайных чисел. Я получил разницу в скорости (~ в два раза быстрее) с третьей попытки, когда мой генератор случайных чисел действительно был вовсе не случайным, а просто брал предварительно сгенерированные числа из массива. В этот момент я понял, что не знаю, что делаю, поэтому я сдался. - person monocell; 15.11.2014

Мвар

  • может быть пустым
  • используется для реализации шаблонов синхронизации между потоками
  • обеспечивает одностороннюю связь между потоками
  • может быть быстрее, чем TVar в некоторых случаях

ТВар

  • не может быть пустым
  • атомарные транзакции
  • «общая память» между потоками; может использоваться для реализации, например, кэша поиска, из которого несколько потоков могут читать/записывать
  • доступ линейное время по количеству операций в журнале транзакций
  • длительные транзакции уязвимы к голоданию, если есть много более коротких транзакций, что препятствует их успешному совершению

IORef

  • изменяемая ссылка в виде указателя
  • часто используется для деструктивной IO записи/обновления
  • имеет атомарные операции CAS, но сложная транзакционная логика лучше подходит для TVar

На самом деле не существует жесткого правила, когда использовать MVar или TVar. Если ресурс, который я охраняю, когда-либо будет «отсутствовать» (в отличие от пустого, рассмотрим Nothing против Just mempty), то MVar часто имеет наибольший смысл. Если мне нужно будет выполнять атомарные блоки модификаций ресурса, то TVar подойдет больше всего.

person cdk    schedule 15.03.2013
comment
Вы ссылаетесь на общие MVar для связи потоков, разве они не должны использоваться только для односторонней связи каждый, потому что, если оба потока обновляют один и тот же MVar для обмена данными между ними, у них будут условия гонки? - person Jimmy Hoffa; 15.03.2013
comment
ты прав. Я не имел в виду, что оба потока будут обновлять один и тот же MVar, я объясню это более ясно. - person cdk; 15.03.2013
comment
Возможно, стоит добавить заметку о голодании. MVars гарантированно будут честными, а TVars — нет. - person hammar; 16.03.2013
comment
@JimmyHoffa у вас может быть несколько шаблонов с MVar, например: одни потоки помещают другие в очередь (по сути, 1-арная очередь FIFO); многие потоки выполняют modifyMVar для изменения некоторого общего состояния; потоки принимают () перед входом в критическую секцию и заменяют при выходе (используя его в качестве блокировки) и т. д. - person jberryman; 28.05.2014