1. Longadder
Ini digunakan dengan cara yang mirip dengan atomiclong, tetapi memiliki kinerja yang lebih baik daripada atomiclong.
Longadder dan atomiclong keduanya menggunakan operasi atom untuk meningkatkan kinerja. Namun, Longadder melakukan pemisahan hot spot berdasarkan atomiclong. Pemisahan hot spot mirip dengan mengurangi ukuran partikel kunci dalam operasi terkunci, memisahkan kunci menjadi beberapa kunci untuk meningkatkan kinerja. Dalam metode bebas kunci, metode serupa dapat digunakan untuk meningkatkan tingkat keberhasilan CAS, sehingga meningkatkan kinerja.
Skema Longadder:
Metode implementasi atomiclong adalah bahwa ada variabel nilai di dalamnya. Ketika banyak utas yang meningkat sendiri dan penangguhan diri, mereka semua dioperasikan dari tingkat instruksi mesin melalui instruksi CAS untuk memastikan atomisitas konkurensi. Satu -satunya alasan yang membatasi efisiensi Atomiclong adalah konkurensi yang tinggi. Konkurensi yang tinggi berarti bahwa CAS memiliki peluang kegagalan yang lebih tinggi, lebih banyak waktu mencoba kembali, dan semakin banyak benang coba lagi, semakin tinggi kemungkinan kegagalan CAS, yang menjadi siklus setan, dan efisiensi atomiclong berkurang.
Longadder akan membagi nilai menjadi beberapa sel, dan menambahkan semua sel ke nilai. Oleh karena itu, saat menambahkan dan mengurangi longadder, Anda hanya perlu beroperasi pada sel yang berbeda. Benang yang berbeda melakukan operasi CAS pada sel yang berbeda. Tentu saja, tingkat keberhasilan CAS tinggi (bayangkan 3+2+1 = 6, satu utas 3+1, utas lainnya 2+1, dan akhirnya 8, longadder tidak memiliki API untuk perkalian dan pembagian).
Namun, ketika angka konkurensi tidak terlalu tinggi, pemisahan menjadi beberapa sel juga membutuhkan pemeliharaan sel dan penjumlahan, yang tidak seefisien implementasi atomiclong. Longadder menggunakan cara cerdas untuk menyelesaikan masalah ini.
Dalam situasi awal, Longadder dan Atomiclong adalah sama. Hanya ketika CAS gagal, nilainya akan dibagi menjadi sel. Setiap kali kegagalan dibuat, jumlah sel akan ditingkatkan. Ini juga efisien dalam konkurensi rendah. Dalam konkurensi tinggi, metode pemrosesan "adaptif" ini tidak akan gagal setelah mencapai sejumlah sel, dan efisiensi akan sangat ditingkatkan.
Longadder adalah strategi bertukar ruang untuk waktu.
2. CompleteFuture
Menerapkan antarmuka penyelesaian panggung (lebih dari 40 metode), yang sebagian besar digunakan dalam pemrograman fungsional. Dan mendukung panggilan streaming
CompleteFuture adalah versi yang ditingkatkan di masa depan di Java 8
Implementasi sederhana:
Impor java.util.concurrent.CompletableFuture; kelas publik AskThread mengimplementasikan runnable {completableFuture <Integer> re = null; Public AskThread (CompletableFuture <Integer> re) {this.re = re; } @Override public void run () {int myre = 0; coba {myre = re.get () * re.get (); } catch (Exception e) {} system.out.println (myre); } public static void main (string [] args) melempar interruptedException {final completeFuture <Integer> future = new completableFuture <Integer> (); utas baru (asktread baru (masa depan)). start (); // Simulasi utas proses perhitungan jangka panjang. Tidur (1000); // menginformasikan hasil penyelesaian Future. }} Hal yang paling dikritik tentang masa depan adalah Anda harus menunggu dan memeriksa apakah tugas telah selesai sendiri. Di masa depan, waktu untuk tugas yang harus diselesaikan tidak dapat dikendalikan. Peningkatan kelengkapan terbesar adalah bahwa waktu untuk penyelesaian tugas juga terbuka.
masa depan. Lapis (60);
Digunakan untuk mengatur waktu penyelesaian.
Eksekusi Fendefuture Asynchronous:
Public Static Integer Calc (Integer ParA) {coba {// Simulasikan Thread Eksekusi Panjang.sleep (1000); } catch (InterruptedException e) {} return paragel *; } public static void main (string [] args) melempar interruptedException, executionException {final completableFuture <Integer> future = completeableFuture .supplyAsync (() -> calc (50)); System.out.println (Future.get ()); } Streaming Call of FulsibleFuture: Public Static Integer Calc (Integer ParA) {coba {// Simulasi utas eksekusi panjang. Tidur (1000); } catch (InterruptedException e) {} return paragel *; } public static void main (string [] args) melempar interruptedException, executionException {completeableFuture <void> fu = completeableFuture .supplyAsync (() -> calc (50)) .thenApply ((i) -> integer.tostring (i)). .thenaccept (System.out :: println); fu.get (); }Gabungkan beberapa CompleteFutures:
Public Static Integer Calc (Integer Para) {return para / 2; } public static void main (string [] args) melempar interruptedException, executionException {completeableFuture <void> fu = completeableFuture .supplyAsync (() -> calc (50)) .thencompose ((i) -> completeFuture.supplyasync (()) .TeCompose (i) -> completeFuture.supplyasync (()). " "/" ") .tenAccept (System.out :: println); fu.get (); } Contoh -contoh ini lebih fokus pada beberapa fitur baru Java 8. Berikut adalah beberapa contoh untuk menggambarkan fitur, jadi saya tidak akan melakukannya secara mendalam.
CompleteFuture tidak ada hubungannya dengan kinerja, tetapi lebih penting untuk mendukung pemrograman fungsional dan peningkatan fungsi. Tentu saja, pengaturan waktu penyelesaian adalah sorotan.
3. Stampedlock
Dalam artikel sebelumnya, pemisahan kunci baru saja disebutkan, dan implementasi penting pemisahan kunci adalah ReadWritelock. Stampedlock adalah peningkatan ReadWritelock. Perbedaan antara Stampedlock dan ReadWritelock adalah bahwa Stampedlock percaya bahwa baca tidak boleh memblokir penulisan, dan Stampedlock percaya bahwa ketika membaca dan menulis saling eksklusif, baca harus dibaca ulang, daripada tidak membiarkan utas menulis untuk menulis. Desain ini memecahkan masalah menulis kelaparan utas saat membaca lebih banyak dan menulis lebih sedikit.
Jadi Stampedlock adalah peningkatan yang cenderung menulis utas.
Contoh Stampedlock:
impor java.util.concurrent.locks.stampedlock; titik kelas publik {private double x, y; Private Final Stampedlock SL = StampedLock baru (); void move (Double Deltax, Double Deltay) {// Metode eksklusif terkunci Long Stamp = sl.writelock (); coba {x += deltax; y += deltay; } akhirnya {sl.unlockwrite (stempel); }} Double DistanceFromoRigin () {// Metode baca-saja Long Stamp = sl.tryoptimisticread (); ganda currentx = x, currenty = y; if (! sl.validate (stamp)) {stamp = sl.readlock (); coba {currentX = x; arus = y; } akhirnya {sl.unlockread (stempel); }} return math.sqrt (currentX * currentx + currenty * currenty); }}Kode di atas mensimulasikan utas penulisan dan utas membaca. Stampedlock memeriksa apakah itu saling eksklusif menurut stempel. Saat menulis stempel sekali, itu meningkatkan nilai tertentu.
tryoptimisticread ()
Ini adalah situasi di mana membaca dan menulis tidak saling eksklusif seperti yang disebutkan.
Setiap kali Anda membaca utas, pertama -tama Anda akan membuat penilaian
if (! sl.validate (stempel))
Dalam validasi, pertama -tama akan memeriksa apakah ada tulisan utas penulisan, dan kemudian menentukan apakah nilai input sama dengan cap saat ini, yaitu, tentukan apakah utas baca akan membaca data terbaru.
Jika ada tulisan utas menulis, atau nilai prangko berbeda, pengembalian gagal.
Jika penilaian gagal, tentu saja Anda dapat mencoba membacanya berulang kali. Dalam kode contoh, tidak diizinkan untuk mencoba membacanya berulang kali, tetapi menggunakan kunci optimisme untuk di -degenerasi menjadi kunci baca biasa untuk membacanya. Situasi ini adalah metode membaca pesimistis.
cap = sl.readlock ();
Ide Implementasi Stampedlock:
CLH Spin Lock: Ketika aplikasi kunci gagal, utas baca tidak akan segera ditangguhkan. Antrian utas yang menunggu akan dipertahankan di kunci. Semua utas yang berlaku untuk kunci, tetapi tidak ada utas yang berhasil dicatat dalam antrian ini. Setiap node (satu node mewakili utas) menyimpan bit yang terkunci untuk menentukan apakah utas saat ini telah melepaskan kunci. Ketika utas mencoba memperoleh kunci, ia memperoleh simpul ekor dari antrian menunggu saat ini sebagai simpul pendahulunya. Dan menggunakan kode seperti berikut untuk menentukan apakah node preambled telah berhasil melepaskan kunci
while (pred.locked) {
}
Loop ini harus menunggu simpul sebelumnya untuk melepaskan kunci, sehingga utas saat ini tidak akan ditangguhkan oleh sistem operasi, sehingga meningkatkan kinerja.
Tentu saja, tidak akan ada putaran tak berujung, dan utas akan ditangguhkan setelah beberapa putaran.