final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) { int h; if ((h = getProbe()) == 0) { ThreadLocalRandom.current(); // force initialization h = getProbe(); wasUncontended = true; } boolean collide = false; // True if last slot nonempty for (;;) { Cell[] as; Cell a; int n; long v; if ((as = cells) != null && (n = as.length) > 0) { if ((a = as[(n - 1) & h]) == null) { if (cellsBusy == 0) { // Try to attach new Cell Cell r = new Cell(x); // Optimistically create if (cellsBusy == 0 && casCellsBusy()) { boolean created = false; try { // Recheck under lock Cell[] rs; int m, j; if ((rs = cells) != null && (m = rs.length) > 0 && rs[j = (m - 1) & h] == null) { rs[j] = r; created = true; } } finally { cellsBusy = 0; } if (created) break; continue; // Slot is now non-empty } } collide = false; } else if (!wasUncontended) // CAS already known to fail wasUncontended = true; // Continue after rehash else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; else if (n >= NCPU || cells != as) collide = false; // At max size or stale else if (!collide) collide = true; else if (cellsBusy == 0 && casCellsBusy()) { try { if (cells == as) { // Expand table unless stale Cell[] rs = new Cell[n << 1]; for (int i = 0; i < n; ++i) rs[i] = as[i]; cells = rs; } } finally { cellsBusy = 0; } collide = false; continue; // Retry with expanded table } h = advanceProbe(h); } else if (cellsBusy == 0 && cells == as && casCellsBusy()) { boolean init = false; try { // Initialize table if (cells == as) { Cell[] rs = new Cell[2]; rs[h & 1] = new Cell(x); cells = rs; init = true; } } finally { cellsBusy = 0; } if (init) break; } else if (casBase(v = base, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; // Fall back on using base } }
Kod itu panjang, mari analisa dalam bahagian, mula-mula perkenalkan kandungan setiap bahagian
Bahagian satu: for
Sebelum gelung Kod ini terutamanya untuk mendapatkan nilai cincang benang Jika ia adalah 0, ia akan dipaksa untuk memulakan
Bahagian 2: for
Pernyataan if
pertama dalam. gelung, dalam Cell
Pengumpulan dan pengembangan dalam tatasusunan
Bahagian 3: for
Pernyataan else if
pertama dalam gelung, fungsi bahagian ini adalah untuk mencipta Tatasusunan Cell
dan mulakan
Bahagian 4: Penyataan for
kedua dalam gelung else if
, apabila persaingan tatasusunan Cell
sengit, cuba kumpulkan pada base
int h; if ((h = getProbe()) == 0) { ThreadLocalRandom.current(); // force initialization h = getProbe(); wasUncontended = true; // true表示没有竞争 } boolean collide = false; // True if last slot nonempty 可以理解为是否需要扩容
Kod teras bahagian ini ialah kaedah getProbe
Fungsi kaedah ini adalah untuk mendapatkan nilai hash
daripada benang, yang sesuai untuk kedudukan kemudian ke dalam tatasusunan Cell
melalui operasi bit Pada kedudukan tertentu, jika ia 0
, pemulaan paksa akan dilakukan
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) { // 省略... for (;;) { Cell[] as; Cell a; int n; long v; if ((as = cells) != null && (n = as.length) > 0) { // 省略... } else if (cellsBusy == 0 && cells == as && casCellsBusy()) { // 获取锁 boolean init = false; // 初始化标志 try { // Initialize table if (cells == as) { Cell[] rs = new Cell[2]; // 创建Cell数组 rs[h & 1] = new Cell(x); // 索引1位置创建Cell元素,值为x=1 cells = rs; // cells指向新数组 init = true; // 初始化完成 } } finally { cellsBusy = 0; // 释放锁 } if (init) break; // 跳出循环 } else if (casBase(v = base, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; // Fall back on using base } }
Dalam kes pertama, tatasusunan Cell
ialah null
, jadi ia akan memasuki pernyataan else if
pertama, dan tiada urutan lain untuk beroperasi, jadi cellsBusy==0
, cells==as
juga true
dan casCellsBusy()
cuba melakukan operasi cellsBusy
pada cas
dan menukarnya kepada 1
, yang juga true
.
mula-mula mencipta tatasusunan Cell
dengan dua elemen, dan kemudian menetapkan h & 1
kepada 1
's value
pada kedudukan indeks 1
melalui operasi bit benang Cell
, Kemudian tetapkan semula kepada cells
, tandakan permulaan berjaya, ubah suai cellsBusy
kepada 0
untuk menunjukkan melepaskan kunci, dan akhirnya lompat keluar dari gelung, operasi pemulaan selesai.
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) { // 省略... for (;;) { Cell[] as; Cell a; int n; long v; if ((as = cells) != null && (n = as.length) > 0) { // 省略... } else if (cellsBusy == 0 && cells == as && casCellsBusy()) { // 省略... } else if (casBase(v = base, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) break; // Fall back on using base } }
Pernyataan else if
kedua bermaksud apabila persaingan untuk semua kedudukan dalam tatasusunan Cell
sengit, cuba kumpulkan pada base
, boleh difahami sebagai jaminan akhir
final void longAccumulate(long x, LongBinaryOperator fn, boolean wasUncontended) { // 省略... for (;;) { Cell[] as; Cell a; int n; long v; if ((as = cells) != null && (n = as.length) > 0) { // as初始化之后满足条件 if ((a = as[(n - 1) & h]) == null) { // as中某个位置的值为null if (cellsBusy == 0) { // Try to attach new Cell 是否加锁 Cell r = new Cell(x); // Optimistically create 创建新Cell if (cellsBusy == 0 && casCellsBusy()) { // 双重检查是否有锁,并尝试加锁 boolean created = false; // try { // Recheck under lock Cell[] rs; int m, j; if ((rs = cells) != null && (m = rs.length) > 0 && rs[j = (m - 1) & h] == null) { // 重新检查该位置是否为null rs[j] = r; // 该位置添加Cell元素 created = true; // 新Cell创建成功 } } finally { cellsBusy = 0; // 释放锁 } if (created) break; // 创建成功,跳出循环 continue; // Slot is now non-empty } } collide = false; // 扩容标志 } else if (!wasUncontended) // 上面定位到的索引位置的值不为null wasUncontended = true; // 重新计算hash,重新定位其他索引位置重试 else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))) // 尝试在该索引位置进行累加 break; else if (n >= NCPU || cells != as) // 如果数组长度大于等于CPU核心数,就不能在扩容 collide = false; // At max size or stale else if (!collide) // 数组长度没有达到最大值,修改扩容标志可以扩容 collide = true; else if (cellsBusy == 0 && casCellsBusy()) { // 尝试加锁 try { if (cells == as) { // Expand table unless stale Cell[] rs = new Cell[n << 1]; // 创建一个原来长度2倍的数组 for (int i = 0; i < n; ++i) rs[i] = as[i]; // 把原来的元素拷贝到新数组中 cells = rs; // cells指向新数组 } } finally { cellsBusy = 0; // 释放锁 } collide = false; // 已经扩容完成,修改标志不用再扩容 continue; // Retry with expanded table } h = advanceProbe(h); // 重新获取hash值 } // 省略... }
Analisis logik keseluruhan mengikut komen dalam kod
Pertama sekali, jika anda cari tatasusunan Nilai pada kedudukan ini ialah null
, menunjukkan bahawa operasi boleh dilakukan pada kedudukan ini Cipta Cell
baharu dan mulakan nilai kepada 1
dan letakkan pada kedudukan ini, kira semula hash
nilai dan cuba lagi
Kedudukan yang diposisikan sudah mempunyai nilai, menunjukkan bahawa terdapat persaingan antara urutan wasUncontended
false
dan kira semula true
Cuba semulahash
sudah wasUncontended
, cuba kumpulkan pada kedudukan itutrue
dan cuba lagi rehash
Jika ia ditandakan sebagai collide
, tukarkannya kepada false
, menunjukkan bahawa kapasiti boleh dikembangkan, dan kemudian true
cuba semula rehash
kali ganda daripada yang sebelumnya, dan kemudian tatasusunan asal kandungan disalin ke tatasusunan baharu, dan pengembangan selesai. 2
Atas ialah kandungan terperinci Apakah status pelaksanaan LongAdder dalam pengaturcaraan serentak Java?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!