В ваших операциях используются разные «версии» сущности из магазина. Рассмотрим этот порядок операций:
Вы создаете 2 операции, назовем их O: F и O: G, которые должны добавить дочерние элементы F и G в группу 1, обозначенные как G: 1 с набором дочерних элементов [A, B, C, D, E ].
Очередь операций одновременно отключает O: F и O: G, поэтому они оба извлекают контекст управляемого объекта и сущность G: 1.
O: F устанавливает детей от G: 1 до [A, B, C, D, E, F].
O: G устанавливает детей из G: 2 в [A, B, C, D, E, G].
Неважно, какая операция выиграет, вы получите либо [A, B, C, D, E, F], либо [A, B, C, D, E, G], оба из которых являются неверные значения в магазине.
Я считаю, что CoreData должен выдавать оптимистическую ошибку блокировки в одном из этих потоков, поскольку его изменения устарели. Но я могу ошибаться.
Суть в том, что вы мутируете один и тот же объект в потоках без синхронизации состояния объекта. Вместо создания 20 операций создайте 1 операцию, которая добавляет 20 объектов, но у вас есть основная архитектурная проблема - попытка изменить один и тот же объект из нескольких потоков без синхронизации.
Это будет терпеть неудачу каждый раз.