Зависит от ваших структур данных.
Я предполагаю, что проблема, с которой вы сталкиваетесь (хотя вы так не говорите), - это потенциальная инверсия блокировки. Если вы выполняете глубокое копирование, вы, вероятно, возьмете одну или несколько блокировок для различных объектов, которые вам нужно скопировать.
Если вы можете определить группу обеспечения доступности баз данных (то есть частичный порядок), где узлы - это все блокировки в системе, и каждая комбинация блокировок, которые вы когда-либо захотите использовать, соединена ребрами, тогда вы можете убедиться, что блокировки никогда не принимается в разных порядках в разных темах. Следовательно, в частности, вы не получите блокировку инверсии. Типичное правило - использовать «самую общую» блокировку последней, поскольку это ведет к минимизации конфликтов.
Но если вы глубоко копируете один из целого набора «виджетов», каждый из которых содержит «виджеты», которые в основном неразличимы, с возможным перекрытием между содержимым ящиков, тогда у вас возникнет проблема с определением порядка блокировки естественным образом. Кроме того, вам сначала нужно заблокировать WidgetBox (даже если это «самый общий» объект), поскольку без этой блокировки вы не можете сказать, что еще нужно заблокировать. Если виджеты сопоставимы, вы можете заблокировать каждый из них по порядку, сделать копию и выпустить все. Противный.
Альтернативой является определение единой блокировки, общей для всех виджетов и WidgetBoxes. Это может вызвать много споров, и в этом случае оптимистическая блокировка может улучшить ситуацию при условии, что одновременно с копиями происходит не слишком много модификаций.
Другая альтернатива может заключаться в том, чтобы ослабить гарантии, которые вы даете в отношении копии - вместо того, чтобы требовать, чтобы полная копия была сделана из идентифицируемого состояния глубокой структуры, вы могли бы сначала заблокировать WidgetBox, поверхностную копию (используя пересчет или любой другой - блокировка на повторном счете обычно является «окончательной внутренней блокировкой» и, следовательно, не является риском инверсии), снимите блокировку WidgetBox, а затем скопируйте каждый из виджетов по очереди. Используйте тот же подход к копированию виджетов, если они имеют внутреннюю структуру. Результат может содержать виджет в состоянии, которого он не достиг до тех пор, пока он не будет удален из WidgetBox в другом потоке, или других подобных несоответствий, поэтому, если это неприемлемо, вы не можете использовать этот подход. Но если вы блокируете только один объект за раз в каждом потоке, вы не сможете получить инверсию блокировки.
Последний, возможный «ядерный» вариант - сделать все неизменным и всегда копировать при модификации. Если ничто не может быть изменено, тогда вам не нужны никакие блокировки (хотя вам все еще нужны барьеры памяти при передаче ссылок между потоками).
Если ни одна из этих работ не работает, значит, вы вне моего опыта, если я что-то не забыл. Я бы предположил, что реализация базы данных - это где-то много хитрости, связанной с блокировками, и это было бы той областью, где нужно искать идеи.