1. Skenario yang berlaku untuk CAS dan disinkronkan
1. Untuk situasi di mana persaingan sumber daya lebih sedikit, menggunakan kunci sinkronisasi yang disinkronkan untuk pemblokiran utas dan operasi switching dan switching antara kernel negara pengguna adalah pemborosan sumber daya CPU ekstra; Sementara CAS diimplementasikan berdasarkan perangkat keras, tidak perlu memasuki kernel, tidak perlu mengganti utas, dan kemungkinan spin operasi lebih sedikit, sehingga kinerja yang lebih tinggi dapat diperoleh.
2. Dalam kasus persaingan sumber daya yang serius, probabilitas putaran CAS relatif tinggi, sehingga membuang lebih banyak sumber daya CPU dan kurang efisien daripada disinkronkan. Mengambil kelas AtomicInteger di paket java.util.concurrent.atomic sebagai contoh, metode getAndincrement () diimplementasikan sebagai berikut:
Public final int getAndIncrement () {for (;;) {int current = get (); int next = arus + 1; if (compareEndset (saat ini, selanjutnya)) Mengembalikan arus; }}Jika metode CompareANDSet (saat ini, berikutnya) berhasil dieksekusi, itu akan dikembalikan secara langsung; Jika kompetisi utasnya sengit, menghasilkan metode CompareEndset (saat ini, berikutnya) yang tidak dapat berhasil dieksekusi, itu akan dilingkarkan dan ditunggu sampai irisan waktu yang dialokasikan oleh CPU ke utas kelelahan, sehingga sangat mengurangi efisiensi.
2. Skenario Penggunaan Kesalahan CAS
kelas publik casdemo {private final int thread_num = 1000; private final int max_value = 20000000; private atomicinteger casi = atomicinteger baru (0); private int synci = 0; Private String Path = "/Users/Pingping/DataCenter/Books/Linux/Linux Commands.txt"; public void casadd () melempar interruptedException {long begin = system.currentTimeMillis (); Thread [] threads = utas baru [thread_num]; untuk (int i = 0; i <thread_num; i ++) {threads [i] = thread baru (runnable baru () {public void run () {while (casi.get () <max_value) {casi.getandincrement ();}}}); utas [i] .start (); } untuk (int j = 0; j <thread_num; j ++) {threads [j] .join (); } System.out.println ("CAS biaya waktu:" + (System.currentTimeMillis () - begin)); } public void syncadd () melempar InterruptedException {long begin = system.currentTimeMillis (); Thread [] threads = utas baru [thread_num]; untuk (int i = 0; i <thread_num; i ++) {threads [i] = utas baru (runnable baru () {public void run () {while (synci <max_value) {disinkronkan ("synci") {++ synci;}}}}}); utas [i] .start (); } untuk (int j = 0; j <thread_num; j ++) utas [j] .join (); System.out.println ("Sinkronisasi Biaya Waktu:" + (System.CurrentTimeMillis () - Begin)); }}Menjalankan CPU inti ganda saya, hasilnya adalah sebagai berikut:
Dapat dilihat bahwa di bawah utas yang berbeda, waktu yang dihabiskan menggunakan perhitungan CAS lebih dari yang disinkronkan. Alasannya adalah baris 15
14 while (casi.get () <max_value) {15 casi.getAndincrement (); 16}Operasi ini merupakan operasi yang sangat memakan waktu. Setelah 15 baris dieksekusi, loop akan segera dimasukkan dan eksekusi akan berlanjut, menghasilkan konflik utas yang serius.
3. Skenario Penggunaan CAS yang Ditingkatkan
Untuk menyelesaikan masalah di atas, hanya perlu untuk membuat waktu eksekusi setiap loop lebih lama, yaitu, ia dapat sangat mengurangi konflik benang. Ubah kode sebagai berikut:
kelas publik casdemo {private final int thread_num = 1000; private final int max_value = 1000; private atomicinteger casi = atomicinteger baru (0); private int synci = 0; Private String Path = "/Users/Pingping/Datacenter/Books/Linux/Linux Command Common Commands penjelasan detail.txt"; public void casadd2 () melempar interruptedException {long begin = system.currentTimeMillis (); Thread [] threads = utas baru [thread_num]; untuk (int i = 0; i <thread_num; i ++) {threads [i] = thread baru (runnable baru () {public void run () {while (casi.get () <max_value) {casi.gandandincrement (); coba (inputStream in = new fileInputStream (file new (jalur)) (); (IoException e) {E.PrintStackTrace ();}}}}); utas [i] .start (); } untuk (int j = 0; j <thread_num; j ++) utas [j] .join (); System.out.println ("CAS Random Biaya Waktu:" + (System.CurrentTimeMillis () - Begin)); } public void syncadd2 () melempar InterruptedException {long begin = system.currentTimeMillis (); Thread [] threads = utas baru [thread_num]; untuk (int i = 0; i <thread_num; i ++) {threads [i] = thread baru (runnable baru () {public void run () {while (synci <max_value) {synchronized ("synci") {++ synci; eB try (inputStream in = newInputStream (-ryput) {++ synci; ear } catch (ioException e) {e.printstacktrace (); utas [i] .start (); } untuk (int j = 0; j <thread_num; j ++) utas [j] .join (); System.out.println ("Sinkronisasi Biaya Waktu:" + (System.CurrentTimeMillis () - Begin)); }}Dalam loop sementara, operasi untuk membaca konten file ditambahkan, yang membutuhkan waktu sekitar 40 ms, sehingga mengurangi konflik utas. Hasil tes adalah sebagai berikut:
Dapat dilihat bahwa ketika konflik sumber daya relatif kecil, metode CAS dan efisiensi sinkronisasi yang disinkronkan serupa. Mengapa CAS tidak mencapai kinerja yang lebih tinggi daripada disinkronkan?
JDK yang digunakan dalam tes adalah 1,7. Mulai dari JDK1.6, banyak optimisasi telah diperkenalkan dengan implementasi kunci, seperti terkunci kunci, eliminasi kunci, penguncian ringan, penguncian bias, pemintalan adaptif dan teknologi lainnya untuk mengurangi overhead operasi kunci. Prinsip kunci spin mirip dengan CAS SPIN, dan bahkan lebih dioptimalkan daripada CAS SPIN. Untuk detailnya, silakan merujuk ke mekanisme kunci JVM yang mendalam 1-sinkronisasi.
4. Ringkasan
1. Saat menggunakan CAS, ketika konflik utas serius, kinerja program akan sangat berkurang; CAS hanya cocok untuk situasi di mana ada lebih sedikit konflik benang.
2. Sinkronisasi telah ditingkatkan dan dioptimalkan setelah JDK1.6. Implementasi yang mendasari sinkronisasi terutama bergantung pada antrian bebas kunci. Ide dasarnya adalah untuk memblokir setelah putaran, terus bersaing untuk mengunci setelah pergantian kompetisi, sedikit mengorbankan keadilan, tetapi mendapatkan throughput tinggi. Ketika ada lebih sedikit konflik utas, kinerja serupa dapat diperoleh; Ketika ada konflik utas yang serius, kinerjanya jauh lebih tinggi daripada CAS.
Ringkasan pemrograman bersamaan Java di atas - menggunakan CAS dengan hati -hati adalah penjelasan rinci dari editor. Saya harap ini dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.