O(1) не допомагає сам по собі. У структурі даних без блокування потрібно мати один атомний екземпляр, коли структура даних, як видається, змінюється. Усі інваріанти представництва повинні діяти як безпосередньо перед, так і безпосередньо після цього атомного моменту.
Це означає, що якщо ви робите модифікацію структури даних, важливою характеристикою є те, що ви можете виконати всі моди на приватній структурі даних, а потім поміняти зміни в одній атомній інструкції.
Захист від блокування зазвичай найпростіший, коли ваші структури даних незмінні ( чисто функціональні ). Ви просто зберігаєте глобальний покажчик на поточну версію структури даних. Читачам не потрібно нічого блокувати. Зміни структури даних здійснюються шляхом заміни глобального вказівника на одну незмінну структуру даних на іншу.
Наприклад: якщо у вас є чисто функціональне дерево, збалансоване дерево, ви:
- Запишіть поточний глобальний покажчик на корінь дерева.
- Створіть нове дерево, яке вставить або видалить вузол. (Це логарифмічно в часі та просторі в кількості вузлів, що перебувають у дереві, і передбачає створення нових вузлів від точки модифікації до кореня, а також просто вказівку на все нове на старі частини попередньої версії структури даних. )
- Атомно порівняйте та замініть глобальний вказівник на корінь. (Зверніть увагу, що це може бути невдалим, якщо відбулася інша модифікація між часом, коли ви записали старий кореневий покажчик і зараз. Якщо це трапиться, ви поверніться до кроку 1 і повторіть спробу. Це так званий "оптимістичний контроль сумісності".)
Зауважте, що найважливіша частина - це те, що я говорив вище про необхідність підтримувати інваріанти представництва. Зазвичай недостатньо мати алгоритм, який атомно вносить зміни в середину дерева. Чому? Наприклад: у вас може бути потік читача, який зараз виконує попереднє обхід дерева. Якщо ви модифікуєте вузол, який є родоначальником вузла, який вони зараз читають, ви збираєтесь визнати недійсними передумови, які, на їхню думку, застосували. Читач повинен мати можливість працювати зі структурою даних точно так, як це було до того, як ви внесли зміни, або точно так, як це буде після внесення змін. Не щось середнє.
Редагувати : Як зазначав @Raphael, існують методи для забезпечення безперешкодної зміни даних. Конструкція підтверджує, що це завжди можна зробити: Поки у вас є єдиний глобальний вказівник на "верх" вашої структури даних, навіть якщо він є змінним, ви завжди можете скопіювати всю структуру даних, зробіть ваші моди в скопіюйте, а потім, використовуючи оптимістичний контроль одночасності, спробуйте порівняти та замінити вказівник на щойно викарбувані структури даних для оригіналу. Краса функціональних структур даних на основі дерева полягає в тому, що вони зберігають витрати на копіювання в структури розміру .O ( N )O(log(N))O(N)