Могу ли я заблокировать элемент в списке, чтобы сделать его потокобезопасным, вместо блокировки всего списка? - PullRequest
0 голосов
/ 25 апреля 2011

Я бы хранил объекты в моем списке std безопасным для потоков способом.Я не хочу блокировать поток, если он хочет получить доступ к элементу, который в данный момент не используется.Если я не могу заблокировать только один элемент, возникает другой вопрос: если я вызову деструктор для одного из моих объектов в списке, удалит ли он элемент и лишит ли его силы итератор?

Ответы [ 3 ]

0 голосов
/ 25 апреля 2011

Могу ли я заблокировать элемент в списке, чтобы сделать его потокобезопасным, вместо блокировки всего списка?

Да, если все потоки используют блокировку при чтении / записи / уничтожении элемента, тогда это безопасно.

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

  • безопасно попытайтесь сделать то же самое с тем же элементом, оспаривая тот же замок

  • добавить другой элемент в список без блокировки

  • НЕ сделать find() в list; find может попытаться прочитать частично обновленную строку

  • НЕ sort() список

  • НЕ erase() элемент из списка

Я не хочу блокировать поток, если он хочет получить доступ к элементу, который в данный момент не используется.

Ну, вам нужен какой-то уровень детализации. Наилучшее возможное - это блокировка для каждого элемента, но это потенциально очень расточительное пространство (а неэффективная память в конечном итоге влияет на производительность).

Если я не могу заблокировать только один элемент, возникает другой вопрос: если я вызову деструктор для одного из моих объектов в списке, удалит ли он элемент и сделает его итератор недействительным?

Нет. Вызов деструктора обычно не влияет на список (если ваши элементы сами не знают, что список содержит их, а их деструкторы закодированы для удаления самих себя). Обычно вместо этого erase элемент из списка, который вызывает деструктор и освобождает связанную память кучи. Если сам элемент является необработанным указателем, то вам нужно вызвать delete для него самостоятельно (smart_pointer автоматизировал это для вас). Итераторы, указатель, ссылки на стертый элемент сразу же становятся недействительными.

0 голосов
/ 25 апреля 2011

Чтобы манипулировать списком, вы должны БЛОКИРОВАТЬ список. После извлечения объекта вы можете снять блокировку списка и блокировку только вокруг объекта.

0 голосов
/ 25 апреля 2011

Как правило, вам необходимо защитить весь экземпляр контейнера списка с помощью блокировки или мьютекса в многопоточной среде.

Если вы храните новые объекты в вашем контейнере, то деструктор будет вызываться только тогда, когда выудаляем указатель на объект.

Дальнейший ответ на ваш вопрос зависит от:

1. Что вы храните в списке?Сам объект или указатель на объект

2. «Если я вызываю деструктор для одного из моих объектов в списке» ... Означает ли это удаление узла списка или извлечение указателя из списка, а затем его удаление?удаления узла списка [Это не хорошо, если вы не укажете указатель на NULL].

Если вы храните сам объект, list.remove вызовет деструктор для объекта.

Если вы храните указатель на объект .. list.remove не будет вызывать деструктор, и я думаю, что он также не работает [исправьте меня, если я ошибаюсь]

3. Стандарт дает гарантию, что итератор списка не будет признан недействительным при добавлении и объединении ... но станет недействительным, если итератор будет указывать на удаленный элемент.

...