Мне нужно создать структуру данных, которая будет использоваться в многопоточной среде. Базовый API прост: вставьте элемент, удалите элемент, извлеките элемент, проверьте, существует ли этот элемент. В реализации структуры используется неявная блокировка, чтобы гарантировать атомарность одного вызова API. После того, как я реализовал это, стало очевидно, что мне действительно нужна атомарность в нескольких вызовах API. Например, если абонент должен проверить существование элемента, прежде чем пытаться вставить его, он не может сделать это атомарно, даже если каждый отдельный вызов API является атомным:Конструкция структуры данных, защищенной потоком
if(!data_structure.exists(element)) {
data_structure.insert(element);
}
пример несколько неудобно, но основной момент заключается в том, что мы больше не можем доверять результату «существующего» вызова после того, как мы вернемся из атомного контекста (сгенерированная сборка явно показывает небольшую вероятность переключения контекста между двумя вызовами).
В настоящее время я имею в виду, что это разрешает блокировку через публичный API структуры данных. Таким образом, клиентам придется явно блокировать вещи, но по крайней мере им не придется создавать свои собственные блокировки. Существует ли более широко известное решение этих проблем? И до тех пор, пока мы на нем, вы можете посоветовать хорошую литературу по потокобезопасному дизайну?
EDIT: У меня есть лучший пример. Предположим, что поиск элемента возвращает либо ссылку, либо указатель на сохраненный элемент, а не копию. Как можно защитить вызывающего абонента, чтобы безопасно использовать этот указатель \ reference после возврата вызова? Если вы считаете, что не возвращать копии, это проблема, а затем подумайте о глубоких копиях, то есть о объектах, которые также должны копировать другие объекты, которые они указывают внутри.
спасибо.
О вас: Подумайте о ситуации, когда указатель на сохраненный элемент возвращен, а другой поток пытается удалить этот элемент из data_structture. Вы, по крайней мере, должны выбрать, какое поведение должно быть реализовано в отношении модели блокировки. Вернуть ошибку в поток, пытающийся удалить объект? дождитесь, пока объект станет неучтенным и т. д. – drlazy