Почему Mutex содержит коробку? [Дубликат]

вы можете «пропустить» поле «ИД» в строке данных, поместив знак разделителя в начало строки, например (для схемы таблицы ID, AField, BField ):

  , afieldvalue, bfieldvalue ...  

при чтении такого файла csv, сценарий будет присваивать NULL полю ID [ ! d5]

30
задан jcoder 26 September 2011 в 16:07
поделиться

2 ответа

Ну ... в основном потому, что я не думаю, что они должны двигаться . Буквально.

В некоторых OS-es мьютекс может быть смоделирован как дескриптор (так что вы можете их скопировать), но IIRC mutex pthreads управляется на месте. Если вы собираетесь переместить это, любая потоковая безопасность будет летать прямо из окна (как другие потоки знают, что мьютекс только что изменил адрес памяти ...)?

33
ответ дан sehe 17 August 2018 в 08:47
поделиться
  • 1
    Ок, я думаю, это имеет смысл :) Я думал об объекте mutex, представляющем мьютекс, чтобы вы могли перенести это на другой объект, но если вы думаете о нем как о будучи мьютекс, тогда нет смысла переместите его, вы правы, – jcoder 26 September 2011 в 17:03
  • 2
    @JohnB: Вы можете делать то, что хотите, с помощью unique_lock<mutex>. Это заблокированный объект (имеет API мьютекса), и его можно перемещать. О, но я бы не разоблачил его сразу несколько потоков. Но вы можете иметь один в каждом потоке, который ссылается на тот же mutex. – Howard Hinnant 26 September 2011 в 17:53
  • 3
    Это объясняло мне проблему. Следствием этого является то, что вы не можете (и не должны) помещать мьютекс непосредственно в контейнер. – T.E.D. 3 December 2014 в 17:00
  • 4
    @ТЕД. За исключением случаев, когда вы можете гарантировать, что хранилище никогда не будет перемещаться (std::array<std::mutex, 100> - это контейнер. Так что boost::intrusive::slist<std::mutex, ...> :)). Но в остальном, да. Вы всегда можете взломать его с помощью shared_ptr<std::mutex> . – sehe 3 December 2014 в 17:01
  • 5
    @sehe - я задал вопрос по этой теме: stackoverflow.com/questions/27276555/… – T.E.D. 3 December 2014 в 17:24

Помните, что C ++ использует принцип «не платите за то, что вы не используете». Рассмотрим, например, мнимую платформу, которая использует непрозрачный тип для представления мьютекса; назовем этот тип mutex_t. Если интерфейс для работы с этим мьютеком использует mutex_t* в качестве аргументов, например, как void mutex_init(mutex_t* mutex); для «создания» мьютекса, вполне может случиться так, что адрес мьютекса - это то, что используется для однозначной идентификации мьютекса. Если это так, то это означает, что mutex_t не копируется:

mutex_t kaboom()
{
    mutex_t mutex;
    mutex_init(&mutex);
    return mutex; // disaster
}

Здесь нет никакой гарантии при выполнении mutex_t mutex = kaboom();, что &mutex имеет то же значение, что и &mutex в функциональный блок.

Когда приходит день, когда разработчик хочет записать std::mutex для этой платформы, если требования этого типа будут подвижными, то это означает, что внутренний mutex_t должен быть помещен в динамически распределенной памяти со всеми связанными штрафами.

С другой стороны, хотя сейчас std::mutex является not подвижным, очень легко «вернуть» один из функция: верните std::unique_ptr<std::mutex>. Это все еще оплачивает затраты на динамическое распределение , но только в одном месте . Все остальные коды, которые не должны перемещать std::mutex, не должны оплачивать это.

Другими словами, поскольку перемещение мьютекса не является основной операцией того, что означает мьютекс , не требуя перемещения std::mutex, не снимает никаких функциональных возможностей (благодаря не подвижной T => подвижной std::unique_ptr<T> трансформации) и будет понести минимальные накладные расходы по сравнению с использованием собственного типа.


std::thread можно было бы аналогичным образом указать, чтобы он не был подвижным, что сделало бы типичное время жизни как таковое: running (связанный с потоком выполнение) после вызова конструктора с оценкой; и отсоединены / объединены (не связаны нитями выполнения), после вызова join или detach. Насколько я понимаю, std::vector<std::thread> все равно был бы полезен, так как тип был бы EmplaceConstructible.

edit: Неверно! Тип все равно должен быть подвижным (при перераспределении в конце концов). Для меня это достаточно обосновано: типично помещать std::thread в контейнеры, такие как std::vector и std::deque, поэтому функциональность приветствуется для этого типа.

16
ответ дан Luc Danton 17 August 2018 в 08:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: