Sebelum membaca artikel ini, Anda dapat membaca " Pendahuluan dan Penggunaan Paket Atom Multithreaded Java " untuk mempelajari tentang konten yang relevan dari paket atom.
1. Apa itu Atom?
Kata atom ada hubungannya dengan atom, yang pernah dianggap sebagai unit materi terkecil. Atom di komputer berarti tidak dapat dibagi menjadi beberapa bagian. Jika sepotong kode dianggap atom, itu berarti bahwa kode tidak dapat terganggu selama eksekusi. Secara umum, instruksi atom disediakan oleh perangkat keras dan disediakan oleh perangkat lunak untuk mengimplementasikan metode atom (utas tidak akan terganggu setelah memasukkan metode sampai eksekusi selesai)
Pada platform X86, CPU menyediakan sarana untuk mengunci bus selama eksekusi instruksi. Ada lead #hlockpin pada chip CPU. Jika awalan "kunci" ditambahkan ke instruksi dalam program bahasa perakitan, kode mesin perakitan akan menyebabkan CPU menurunkan potensi #hlockpin saat menjalankan instruksi ini, dan melepaskannya sampai akhir instruksi ini, sehingga mengunci bus. Dengan cara ini, CPU lain di bus yang sama tidak dapat mengakses memori melalui bus untuk sementara waktu, memastikan atomisitas instruksi ini dalam lingkungan multiprosesor.
2. Variabel atom di java.util.concurrent
Apakah langsung atau tidak langsung, hampir semua kelas di java.util.concurrent Paket menggunakan variabel atom, bukan sinkronisasi. Kelas-kelas seperti ConcurrentLinkedQueUe juga menggunakan variabel atom untuk secara langsung mengimplementasikan algoritma free-free, sementara kelas-kelas seperti ConcurrhenthMap menggunakan reentrantlock untuk mengunci saat dibutuhkan. Reentrantlock kemudian menggunakan variabel atom untuk mempertahankan antrian utas menunggu penguncian.
Tanpa perbaikan JVM di JDK5.0, kelas-kelas ini tidak akan dibangun, yang mengekspos (ke perpustakaan kelas, bukan kelas pengguna) antarmuka untuk mengakses primitif sinkronisasi tingkat perangkat keras. Kelas variabel atom dan kelas lain di java.util.concurrent kemudian mengekspos fungsi -fungsi ini ke kelas pengguna
kelas atom java.util.concurrent.atomic
Paket ini menyediakan satu set kelas atom. Fitur dasarnya adalah bahwa dalam lingkungan multi-threaded, ketika beberapa utas mengeksekusi metode yang terkandung dalam contoh kelas-kelas ini pada saat yang sama, itu eksklusif, yaitu, ketika utas memasuki metode dan menjalankan instruksi di dalamnya, tidak akan terganggu oleh utas lain, dan utas lainnya seperti kunci putaran. Sampai metode dieksekusi, JVM akan memilih utas lain dari antrian menunggu untuk masuk. Ini hanya pemahaman yang logis. Bahkan, itu diimplementasikan dengan bantuan instruksi perangkat keras yang relevan dan tidak akan memblokir utas (atau hanya diblokir di tingkat perangkat keras). Kelas dapat dibagi menjadi 4 kelompok
Atomicboolean, atomicinteger, atomiclong, atomicreference
AtomicIntegerarray, Atomiclongarray
Atomiclongfieldupdater, atomicintegerfieldupdater, atomicreferenceFieldupdater
AtomicmarkableReer, atomicstampedreference, atomicreferenceArray
Di antara mereka, atomicboolean, atomicinteger, atomiclong, atomicreference serupa.
Pertama -tama, atomicboolean, atomicinteger, atomiclong, atomicreference internal API serupa: ambil contoh atomikreferensi
Buat tumpukan yang aman dari benang dengan referensi atomik
kelas publik LinkedStack <T> {private atomicreference <node <t>> stacks = atomicreference baru <node <t>> (); public t push (t e) {node <t> oldnode, newnode; while (true) {// Pemrosesan di sini sangat istimewa, dan itu harus terjadi. oldNode = stacks.get (); newNode = new node <t> (e, oldnode); if (stacks.com compareandset (oldnode, newnode)) {return e;}}} public t pop () {node <t> oldnode, newnode; while (true) {oldnode = stackget (node <t> oldnode, newnode; while (true) {oldnode = stackget (stackget); (stacks.compareandset (oldnode, newnode)) {return oldnode.object;}}} private static class class node <t> {private t objek; node pribadi <t> next; node private (t object, node <t> next) {this.object = object; this.next = next;Kemudian fokus pada pembaruan atom lapangan.
Atomicintegerfieldupdater <T>/Atomiclongfieldupdater <T>/AtomicReferenceFieldUpdater <T, V> adalah nilai bidang berdasarkan refleksi.
API yang sesuai juga sangat sederhana, tetapi juga memiliki beberapa kendala.
(1) Bidang harus dari tipe volatile! Apa itu volatile? Silakan periksa " Penjelasan Detail Kata Kunci yang mudah menguap di Java "
(2) Jenis deskripsi bidang (pengubah publik/terlindungi/default/pribadi) konsisten dengan hubungan antara penelepon dan bidang objek operasi. Dengan kata lain, penelepon dapat secara langsung mengoperasikan bidang objek, dan kemudian merefleksikan dan melakukan operasi atom. Namun, untuk bidang kelas induk, subkelas tidak dapat dioperasikan secara langsung, meskipun subkelas dapat mengakses bidang kelas induk.
(3) Ini hanya bisa berupa variabel instan, bukan variabel kelas, yaitu, tidak dapat menambahkan kata kunci statis.
(4) Ini hanya dapat dimodifikasi variabel, dan tidak dapat dibuat menjadi variabel akhir, karena semantik final tidak dimodifikasi. Faktanya, semantik konflik akhir dan volatile, dan dua kata kunci ini tidak dapat ada pada saat yang sama.
(5) Untuk AtomicIntegerfieldUpdater dan AtomiclongfieldUpdater, mereka hanya dapat memodifikasi bidang tipe int/panjang, dan tidak dapat memodifikasi tipe pembungkusnya (integer/long). Jika Anda ingin memodifikasi jenis pembungkus, Anda perlu menggunakan AtomicReferenceFieldUpdater.
Metode operasi dijelaskan dalam contoh berikut.
Impor java.util.concurrent.atomic.atomicintegerfieldupdater; kelas publik atomicintegerfieldupdaterDemo {kelas demodata {volatile publik value nilai1 = 1; volatile int value2 = 2; volatile volatile yang dilindungi 2; 3; value volatile volatile privat4 = 4;} atom;} atoMAcaPereCeTeTeTeT 3; private volatile int value4 = 4;} atom; atom volatile yang dilindungi3 = 3; private volatile value value4 = 4;} atoMAcaPerate fieldName) {return atomicintegerfieldupdater.newupdater (demodata.class, fieldName);} batal doit () {Demodata data = demodata baru (); System.out.println ("1 ==>"+getUpdater ("value1"). GetSandset, 10). "+getUpdater (" value2 "). Incrementandget (data)); System.out.println (" 2 ==> "+getUpdater (" value3 "). Decrementandget (data)); System.out.println (" true ==> "+getUpdater (" value4 "). CompareanDSet (Data, 4,) {AtomicintegerfieldupdaterDemo demo = atomicintegerfieldupdaterDemo baru (); demo.doit ();}}Dalam contoh di atas, nilai bidang3/nilai4 dari demodata tidak terlihat oleh kelas AtomicIntegerfieldupdaterDemo, sehingga nilainya tidak dapat dimodifikasi secara langsung melalui refleksi.
Sepasang <objek, boolean> yang dijelaskan oleh kelas atomicmarkableRerence dapat secara atom memodifikasi nilai objek atau boolean. Struktur data ini lebih berguna dalam beberapa cache atau deskripsi negara. Struktur ini dapat secara efektif meningkatkan throughput saat memodifikasi objek/boolean secara individual atau secara bersamaan.
Kelas atomicstampedreference mempertahankan referensi objek dengan "bendera" integer dan dapat diperbarui secara atom. Dibandingkan dengan <objek, boolean> dari kelas atomicmarkableRererence, atomicstampedreference mempertahankan struktur data yang mirip dengan <objek, int>, yang sebenarnya merupakan jumlah objek bersamaan (referensi). Tetapi tidak seperti AtomicInteger, struktur data ini dapat membawa referensi objek dan dapat melakukan operasi atom pada objek ini dan menghitung pada saat yang sama.
"ABA Problem" akan disebutkan di akhir artikel ini, dan atomicmarkableReFerence/atomicstampedreference berguna dalam memecahkan "masalah ABA".
AKU AKU AKU. Peran atom
Ini memungkinkan pengoperasian data tunggal yang diatomisasi
Bangun kode yang kompleks dan bebas memblokir menggunakan kelas atom
Mengakses 2 atau lebih variabel atom (atau melakukan 2 atau lebih operasi pada variabel atom tunggal) umumnya dianggap memerlukan sinkronisasi sehingga operasi ini dapat digunakan sebagai unit atom.
Tidak ada penguncian dan tidak ada algoritma yang menunggu
Algoritma konkurensi berdasarkan CAS (CompareandsWap) disebut algoritma bebas-kunci karena utas tidak harus menunggu untuk mengunci lagi (kadang-kadang disebut mutex atau bagian kritis, tergantung pada terminologi platform utas). Apakah operasi CAS berhasil atau gagal, dalam kedua kasus, itu selesai dalam waktu yang dapat diprediksi. Jika CAS gagal, penelepon dapat mencoba lagi operasi CAS atau mengambil operasi lain yang sesuai.
Jika setiap utas terus beroperasi ketika utas lain ditunda (atau bahkan gagal), dapat dikatakan bahwa algoritma tersebut bebas menunggu. Sebaliknya, algoritma bebas-kunci mensyaratkan bahwa hanya utas tertentu yang selalu melakukan operasi. (Definisi lain dari No Wait adalah untuk memastikan bahwa setiap utas dengan benar menghitung operasinya sendiri dalam langkah -langkahnya yang terbatas, terlepas dari operasi, waktu, crossover, atau kecepatan utas lainnya. Batas ini dapat menjadi fungsi dari jumlah utas dalam sistem; misalnya, jika ada 10 utas, masing -masing utas akan melakukan rety.
Selama 15 tahun terakhir, orang telah melakukan penelitian ekstensif tentang algoritma bebas menunggu dan bebas kunci (juga dikenal sebagai algoritma non-blocking), dan banyak orang telah menemukan algoritma non-blocking dalam struktur data umum. Algoritma non-blocking banyak digunakan pada sistem operasi dan tingkat JVM, melakukan tugas seperti threading dan penjadwalan proses. Meskipun implementasinya lebih kompleks, mereka memiliki banyak keunggulan dibandingkan algoritma alternatif berbasis kunci: mereka dapat menghindari bahaya seperti inversi prioritas dan kebuntuan, persaingan lebih murah, koordinasi terjadi pada tingkat granularitas yang lebih baik, memungkinkan untuk tingkat paralelisme yang lebih tinggi, dan sebagainya.
Umum:
Penghitung non-blocking
Stack ConcurrentStack non-blocking
Daftar Tertaut Non-Blocking ConcurrentLinkedQueue
Pertanyaan ABA:
Karena sebelum mengubah V, CAS terutama menanyakan "apakah nilai V masih A", sebelum membaca V untuk pertama kalinya dan melakukan operasi CAS pada V, mengubah nilai dari A ke B dan kemudian kembali ke A akan membingungkan algoritma berbasis CAS. Dalam hal ini, operasi CAS akan berhasil, tetapi dalam beberapa kasus hasilnya mungkin bukan yang Anda harapkan. Jenis masalah ini disebut masalah ABA, yang biasanya ditangani dengan mengaitkan tag atau nomor versi dengan setiap nilai yang akan dilakukan pada operasi CAS dan secara atom memperbarui nilai dan tag. Kelas atomicstampedreference mendukung metode ini.
Meringkaskan
Di atas adalah semua penjelasan terperinci dari artikel ini tentang pengoperasian variabel atom dan kelas atom dalam paket atom multi-threaded Java. Saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke situs ini:
Pemrograman Java: Kebuntuan multi-thread dan komunikasi antar utas adalah kode sederhana
Java Multi-Threaded Programming Contoh kecil mensimulasikan sistem tempat parkir
Diskusi singkat tentang keuntungan dan contoh kode java multithreading
Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya.