Mari kita analisa proses pelaksanaan asasnya berdasarkan kod sumber.
Kelas ini biasanya lebih disukai daripada AtomicLong apabila berbilang urutan mengemas kini jumlah biasa yang digunakan untuk tujuan seperti mengumpul statistik, bukan untuk kawalan penyegerakan yang terperinci Di bawah perbalahan kemas kini yang rendah, kedua-dua kelas mempunyai ciri yang serupa. Tetapi di bawah pertikaian yang tinggi, jangkaan daya pengeluaran kelas ini adalah lebih tinggi dengan ketara, dengan mengorbankan penggunaan ruang yang lebih tinggi.
Perenggan di atas adalah sebahagian daripada LongAdder
ulasan kod sumber, diterjemahkan The maksudnya kira-kira
Kelas ini biasanya lebih baik daripada AtomicLong
apabila berbilang urutan mengemas kini jumlah biasa yang digunakan untuk mengumpul statistik tetapi bukan untuk tujuan kawalan penyegerakan yang terperinci. Di bawah perbalahan kemas kini rendah, kedua-dua kelas ini mempunyai ciri yang serupa. Tetapi di bawah keadaan perbalahan yang tinggi, daya pengeluaran yang dijangkakan bagi kelas ini jauh lebih tinggi, tetapi pada kos penggunaan ruang yang lebih tinggi.
Dalam erti kata lain, LongAdder
lebih cekap apabila konkurensi tinggi, tetapi kosnya adalah ruang untuk masa.
Mari kita terangkan prinsip LongAdder
dengan cara yang mudah: apabila konkurensi adalah rendah, sudah cukup untuk melakukan operasi pengumpulan pada hanya satu pembolehubah base
, jadi ia serupa dengan AtomicLong
; tetapi apabila konkurensi meningkat , jika anda masih beroperasi pada pembolehubah base
, banyak utas akan disekat, jadi buat tatasusunan cells
, dan kumpulkan setiap elemen tatasusunan, dan kemudian hitung hasil akhir base
dan cells
hanyalah jumlah setiap elemen tatasusunan. Bit khusus dalam tatasusunan tempat benang beroperasi boleh ditentukan dengan mengira hash
untuk menentukan kedudukan indeks.
LongAdder
Atribut yang diwarisi daripada kelas induk Striped64
Cell
di sini ialah kelas dalaman yang digunakan untuk operasi pengumpulan. Terdapat value
Harta dalaman untuk menyimpan nilai terkumpul.
// CPU核心数 static final int NCPU = Runtime.getRuntime().availableProcessors(); // 并发高时进行累加的Cell数组 transient volatile Cell[] cells; // 多个线程没有竞争时在base上进行累加 transient volatile long base; // Cell数组是否正在创建或扩容 transient volatile int cellsBusy;
Kaedah operasi pengumpulan increment()
sebenarnya memanggil add(1L)
, jadi mari kita lihat terus pada kaedah add
public void add(long x) { Cell[] as; long b, v; int m; Cell a; if ((as = cells) != null || !casBase(b = base, b + x)) { boolean uncontended = true; // 表示没有竞争 if (as == null || (m = as.length - 1) < 0 || (a = as[getProbe() & m]) == null || !(uncontended = a.cas(v = a.value, v + x))) longAccumulate(x, null, uncontended); } }
Mula-mula, mari lihat penyataan if
pertama, pernyataan awal situasi cells
seterusnya ialah null
, jadi operasi casBase
akan dilakukan, iaitu pembolehubah base
akan terkumpul Jika operasi berjaya, bermakna tiada persaingan pada masa ini, jadi ia sudah berakhir.
Apabila konkurensi meningkat, kaedah casBase
mungkin gagal, jadi pada masa ini, penghakiman pernyataan if
kedua dimasukkan.
Apabila ia masuk buat kali pertama, Cell
tatasusunanas
ialah null
, jadi longAccumulate
akan dilaksanakan dan Cell
tatasusunanas
akan dimulakan dan diindeks 1
Pengumpulan kedudukan 1
;
dan kemudian melaksanakan pernyataan if
ini bukan lagi as
, dan panjang tatasusunan ialah juga lebih besar daripada null
0
, pemahaman mudah ayat ini ialah mencari kedudukan indeks secara rawak dalam tatasusunan a = as[getProbe() & m]) == null
, dan menentukan sama ada nilai kedudukan itu ialah as
, jika ia null
Hanya laksanakan null
bukannya longAccumulate
dan teruskan menilai null
Ayat ini bermaksud operasi pengumpulan dilakukan pada kedudukan indeks yang ditemui Jika berjaya, Tamatkan operasi, jika gagal, laksanakan !(uncontended = a.cas(v = a.value, v + x))
longAccumulate
Atas ialah kandungan terperinci Analisis kod sumber LongAdder bagi pengaturcaraan serentak Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!