В этой статье в основном изучаются контент о проблемах и избегании АБА в Java, следующим образом.
В главе 15 книги «Практическая практика параллелизма Java» существует стек параллелизма, реализованный с использованием атомных переменных, и код выглядит следующим образом:
Общественный класс Node {public final String Item; public node Next; public node (string item) {this.item = item;}} Общедоступный класс comproundstack {atomicReference <node> top = new AtomicReference <node> (); pop () {node newtop; node oldtop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldtop.next;} while (!Этот пример не вызовет проблемы с АБА. Что касается того, почему это не так, я объясню это позже. Давайте сначала поговорим о проблемах ABA.
Что такое Аба?
Цитируйте оригинальную книгу: Если узлы в алгоритме могут использоваться циклически, эта проблема может возникнуть при использовании инструкции «Сравнить и обмен». В операции CAS будет признано, что «стоимость V все еще а?», И если да, то операция обновления будет продолжаться. В некоторых алгоритмах, если значение V сначала изменяется от A на B, а затем от B на A, то CAS будет успешно работать.
Примеры аба
Иногда последствия, вызванные АБА, очень серьезны. Давайте изменим пример стека параллелизма, чтобы увидеть, какие проблемы будут вызывать ABA:
Общественный класс Node {public final String Item; public node Next; public node (string item) {this.item = item;}} открытый класс comproundstack {atomicReference <node> top = new AtomicReference <node> (); OldTop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldtop.next; timeUnit.seconds.sleep (time);} while (!Обратите внимание на изменения здесь, узел в основном не изменился
Сосредоточьтесь на изменениях в одновременном
1. Метод PUSH: Первоначально, используя контент для построения узла, но теперь непосредственно проходит в узле, что соответствует требованию «узлов в алгоритме может быть переработана»
2. Сон метода POP, который имитирует выполнение потока, чтобы наблюдать за результатами.
Давайте сначала нажмите два узла в стек:
ConcurrentStack Stack = new ComarrentStack (); stack.push (new Node ("a")); stack.push (new Node ("b"));Затем создайте два потока для выполнения операций, входящих и выходящих из стека
Поток первой выполняет стекает: Let Nodea из стека
stack.pop (3);
По какой -то причине, нить A был выполнен в течение длительного времени и использовал 3 секунды
Поток B выполняет стек, а затем входит в стек: сначала выпускаются Nodea и Nodeb, а затем введены Nodec, Nodec и Nodea (Nodea находится в верхней части стека)
Узел a = Stack.pop (0); stack.pop (0); stack.push (new Node ("D")); stack.push (new Node ("c")); stack.push (a);Примечание. Поток B реализует утилизацию узлов. Сначала он выпускает все содержимое в стеке, а затем помещает их в стек. Наконец, контент в верхней части стека - это узел, который был выпущен ранее.
После того, как поток B выполнил эти действия, поток A выполнит CAS. В настоящее время CAS может успешно выполнить.
Согласно оригинальной идее, после потоков A и B выполняется, содержимое стека должно быть: C и D, C находится в верхней части стека, но результат выполнения здесь заключается в том, что в стеке нет ничего, что является проблемой ABA.
Как избежать проблем с АБА
AtomicStampedReference и AtomicMarkAbleReerference предоставлены на Java для решения проблем ABA
AtomicStampedReference может атомно обновлять два значения: ссылка и номер версии, а также различать использование цикла узла по номеру версии. Давайте посмотрим на пример AtomicStampedReference:
Общедоступный класс comproundStack {atomicStampedReference <node> top = new AtomicStampedReference <node> (null, 0); public void push (узлы узла) {node oldtop; int v; do {v = top.getStamp (); OldTop = top.getReference (); node.next = oldTop; Node, V, V+1)); //} while (! top.compareAndset (oldtop, node, top.getstamp (), top.getstamp ()+1));} public node pop (int time) {node newtop; node oldtop; int v; do {v = top.getStamp (); oldTop = top.get.GetRection (); if ullyop (); null;} newtop = oldtop.next; try {timeUnit.seconds.sleep (time);} catch (прерывание Exception e) {e.printstacktrace ();}} while (! top.compareandeset (oldtop, newtop, v, v+1); //} while (! newtop, top.getstamp (), top.getstamp ())); return oldtop;} public void get () {node node = top.getReference (); while (node! = null) {System.out.println (node.getitem ()); node = node.getNode ();}}}Примечание. Вы не можете использовать метод комментариев, в противном случае он ничем не отличается от простого использования атомных переменных.
AtomicMarkAbleReerference может атомально обновить биты и типы эталонного типа логического типа, см. Следующий пример:
AtomicmarkAbleReerference <node> top = new AtomicMarkAbleReerference <node> (null, true); public void push (узловой узел) {node oldtop; boolean v; do {v = top.ismarked (); oldtop = top.getReference (); node.next = oldTop;} whing (!Суммировать
Вышеупомянутое содержание этой статьи о кратком обсуждении проблем с АБА и избегания в Java. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!