Artikel ini terutama mempelajari konten terkait tentang masalah ABA dan penghindaran di Java, sebagai berikut.
Dalam Bab 15 buku "Praktik Praktis Java Concurrency", ada tumpukan konkurensi yang diimplementasikan menggunakan variabel atom, dan kodenya adalah sebagai berikut:
Node kelas publik {item string akhir publik; node publik selanjutnya; node publik (item string) {this.item = item;}} kelas publik concurrentStack {atomicreference <node> top = atomicreference baru <node> (); public void push (item string) {node newtop = new node (item); node oldtop; do {oldtop = top.get (); newtop.next = oldtop;} while {! pop () {node newtop; node oldtop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldtop.next;} while (! top.compareandset (oldtop, newtop)); return oldtop.item;}}Contoh ini tidak akan menyebabkan masalah ABA. Adapun mengapa tidak, saya akan menjelaskannya nanti. Mari kita bicara tentang masalah ABA terlebih dahulu.
Apa itu Aba?
Kutip buku asli: Jika node dalam algoritma dapat digunakan secara siklis, masalah ini dapat terjadi ketika menggunakan instruksi "Bandingkan dan pertukaran". Dalam operasi CAS, akan dinilai bahwa "apakah nilai V masih a?", Dan jika demikian, operasi pembaruan akan berlanjut. Dalam beberapa algoritma, jika nilai V pertama berubah dari A ke B dan kemudian dari B ke A, maka CAS akan beroperasi dengan sukses.
Contoh ABA
Terkadang, konsekuensi yang disebabkan oleh ABA sangat serius. Mari kita ubah contoh tumpukan konkurensi untuk melihat masalah apa yang akan disebabkan ABA:
Node kelas publik {item string akhir publik; node publik selanjutnya; node publik (item string) {this.item = item;}} kelas publik concurrentStack {atomicreference <node> top = atomicreference baru <node> (); public void push (node node) {node oldtop; do {oldtop = top.get (); node.next = oldtop; while while (! Top.comppeppeppeppeppepeiDset (oldtop, node. Oldtop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldtop.next; timeunit.seconds.sleep (waktu);} while}}}}}}}}}}}}}}}}}}}}}Perhatikan perubahan di sini, Node pada dasarnya tidak berubah
Fokus pada perubahan di ConcurrentStack
1. Metode Push: Awalnya, menggunakan konten untuk membuat simpul, tetapi sekarang langsung lulus dalam simpul, yang memenuhi persyaratan "node dalam algoritma dapat didaur ulang"
2. Tidur metode pop, yang mensimulasikan eksekusi utas untuk mengamati hasilnya.
Mari pertama -tama tekan dua node ke dalam tumpukan:
Stack ConcurrentStack = ConcurrentStack baru (); stack.push (node baru ("a")); stack.push (node baru ("b"));Kemudian buat dua utas untuk melakukan operasi yang masuk dan meninggalkan tumpukan
Thread yang pertama mengeksekusi penumpukan: Biarkan nodea keluar dari tumpukan
stack.pop (3);
Untuk beberapa alasan, Thread A telah dieksekusi sejak lama dan telah menggunakan 3 detik
Thread B mengeksekusi tumpukan dan kemudian memasuki tumpukan: pertama, nodea dan nodeB dilepaskan, dan kemudian dibiarkan noded, nodec, dan nodea dimasukkan (nodea berada di bagian atas tumpukan)
Node a = stack.pop (0); Stack.pop (0); stack.push (node baru ("d")); stack.push (node baru ("c")); stack.push (a);Catatan: Thread B mengimplementasikan daur ulang node. Pertama -tama melepaskan semua konten di tumpukan, dan kemudian memasukkannya ke dalam tumpukan. Akhirnya, konten di bagian atas tumpukan adalah simpul yang dirilis sebelumnya.
Setelah Thread B melakukan tindakan ini, utas A akan mengeksekusi CAS. Pada saat ini, CAS dapat dieksekusi dengan sukses.
Menurut ide aslinya, setelah utas A dan B dieksekusi, konten tumpukan harus: C dan D, C berada di bagian atas tumpukan, tetapi hasil eksekusi di sini adalah tidak ada yang ada dalam tumpukan, yang merupakan masalah ABA.
Bagaimana menghindari masalah aba
Atomicstampedreference dan AtomicmarkableReRerence disediakan di Java untuk menyelesaikan masalah ABA
AtomicstampedReference dapat secara atom memperbarui dua nilai: nomor referensi dan versi, dan membedakan penggunaan siklus node dengan nomor versi. Mari kita lihat contoh atomicstampedreference:
public class ConcurrentStack {AtomicStampedReference<Node> top = new AtomicStampedReference<Node>(null,0);public void push(Node node){Node oldTop;int v;do{v=top.getStamp();oldTop = top.getReference();node.next = oldTop;}while(!top.compareAndSet(oldTop, node, v, v+1)); //} while (! Top.Compareandset (oldtop, node, top.getstamp (), top.getstamp ()+1));} node publik pop (waktu int) {node newtop; node oldtop; int v; do {v = top.getstamp (); node node (node (); node {node (); node {node (); node {node {node (); null;} newtop = oldtop.next; coba {timeunit.seconds.sleep (time);} catch (interruptedException e) {e.printstacktrace ();}} while (! Top.coCpepPareanDset (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 ();}}}Catatan: Anda tidak dapat menggunakan metode komentar, jika tidak, itu tidak akan berbeda dengan hanya menggunakan variabel atom.
AtomicmarkableReer dapat secara atomik memperbarui bit tipe penanda dan jenis referensi boolean, lihat contoh berikut:
AtomicmarkableReFerence <node> top = atomicmarkableReference baru <node> (null, true); public void push (node node) {node oldtop; boolean v; do {v = top.ismarked (); oldtop = top.getReference (); node.next = oldtop; while) while. node, v,! v));}Meringkaskan
Di atas adalah semua isi artikel ini tentang diskusi singkat tentang masalah ABA dan penghindaran di Java. Saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!