AtomicInteger lazySet ve set karşılaştırması


116

lazySetVe setyöntemleri arasındaki fark nedir AtomicInteger? Dokümantasyon hakkında söylenecek çok şey yok lazySet:

Sonunda verilen değere ayarlar.

Görünüşe göre, saklanan değer hemen istenen değere ayarlanmayacak, bunun yerine gelecekte bir süre ayarlanacak şekilde planlanacak. Peki bu yöntemin pratik kullanımı nedir? Herhangi bir örnek?

Yanıtlar:


114

Doğrudan "JDK-6275329: Atomik sınıflara lazySet yöntemleri ekleyin" den alıntı :

Muhtemelen Mustang için son küçük JSR166 takibi olarak, Atomic sınıflarına (AtomicInteger, AtomicReference, vb.) Bir "lazySet" yöntemi ekledik. Bu, bazen engellemeyen veri yapılarını kullanarak kodda ince ayar yaparken faydalı olan niş bir yöntemdir. Anlambilim, yazmanın önceki herhangi bir yazma ile yeniden sıralanmayacağının garanti edilmesidir, ancak sonraki işlemlerle yeniden sıralanabilir (veya eşdeğer olarak, başka bir uçucu yazma veya senkronizasyon eylemi gerçekleşene kadar diğer iş parçacıkları tarafından görünmeyebilir).

Ana kullanım durumu, yalnızca uzun vadeli çöp tutmadan kaçınmak amacıyla, engellemeyen veri yapılarındaki düğüm alanlarını boşa çıkarmak içindir; diğer evreler bir süre boş olmayan değerler görürse zararsız olduğunda uygulanır, ancak yapıların sonunda GCable olmasını sağlamak istersiniz. Bu gibi durumlarda, boş uçucu yazma maliyetlerinden kaçınarak daha iyi performans elde edebilirsiniz. Referans temelli olmayan atomlar için de bu satırlar boyunca birkaç başka kullanım durumu vardır, bu nedenle yöntem tüm AtomicX sınıflarında desteklenir.

LazySet, bu işlemleri ortak çoklu işlemcilerdeki makine seviyesindeki engeller açısından düşünmeyi seven kişiler için, önden gelen bir mağaza-mağaza bariyeri sağlar (mevcut platformlarda işlemsiz veya çok ucuzdur), ancak mağaza yükü engeli yoktur. (bu genellikle uçucu bir yazının pahalı kısmıdır).


14
Birisi geri kalanımız için bunu kısaltabilir mi? :(
Gaurav

14
Tembel, uçucu olmayan versiyondur (örneğin, durum değişikliğinin Atomic*kapsam dahilindeki tüm evreler tarafından görülmesi garanti edilmez ).
esneme

63
anlamadığım şey javadoc'un neden bu kadar zayıf olduğu.
Felipe

8
Eminim sonunda onu değiştireceklerdir. Bom Bom.
MMJZ

3
mağaza / yük bariyerini ve neden mağaza-mağaza bariyerinin mağaza yükleme bariyerinden daha ucuz olduğunu öğrenmek isteyenler için. İşte bununla ilgili anlaşılması kolay bir makale. mekanik-sympathy.blogspot.com/2011/07/…
Kin Cheung

15

lazySet, rmw inter thread iletişimi için kullanılabilir, çünkü xchg atomiktir, görünürlük açısından, yazıcı iş parçacığı işlemi bir önbellek satırı konumunu değiştirdiğinde, okuyucu iş parçacığının işlemcisi bunu bir sonraki okumada görecek, çünkü intel cpu'nun önbellek tutarlılık protokolü garantili olacaktır LazySet çalışıyor, ancak önbellek satırı bir sonraki okumada güncellenecek, yine CPU'nun yeterince modern olması gerekiyor.

http://sc.tamu.edu/systems/eos/nehalem.pdf Çok işlemcili bir platform olan Nehalem için işlemciler, diğer işlemcilerin sistem belleğine erişimleri için adres veriyolunu "gözetleme" (gizli dinleme) ve dahili önbelleklerine. Dahili önbelleklerini hem sistem belleğiyle hem de birbirine bağlı diğer işlemcilerdeki önbelleklerle tutarlı tutmak için bu gözetleme yeteneğini kullanırlar. Bir işlemci, gözetleme yoluyla, başka bir işlemcinin Paylaşılan durumda o anda önbelleğe aldığı bir bellek konumuna yazma niyetinde olduğunu tespit ederse, gözetleme işlemcisi, önbellek bloğunu geçersiz kılarak, aynı bellek konumuna bir daha eriştiğinde bir önbellek satırı doldurmaya zorlar. .

x86 cpu mimarisi için oracle hotspot jdk->

lazySet == unsafe.putOrderedLong == xchg rw (nehelem intel cpu üzerinde 20 çevrime mal olan yumuşak bir bariyer görevi gören asm talimatı)

x86 (x86_64) üzerinde böyle bir engel, performans açısından uçucu veya AtomicLong getAndAdd'den çok daha ucuzdur,

Bir üreticide, tek bir tüketici kuyruğu senaryosunda, xchg soft barrier, üretici iş parçacığı için yeni verileri tüketecek (üzerinde çalışacak) herhangi bir tüketici iş parçacığı kodundan ÖNCE kod satırını lazySet'ten (sıra + 1) önce zorlayabilir. tüketici iş parçacığının, bir ComparAndSet (sıra, sıra + 1) kullanarak üretici sırasının tam olarak bir arttığını atomik olarak kontrol etmesi gerekecektir.

LazySet'in cpp koduna tam olarak eşlenmesini bulmak için Hotspot kaynak kodunun izini sürdüm: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe. cpp Unsafe_setOrderedLong -> SET_FIELD_VOLATILE tanımı -> OrderAccess: release_store_fence. X86_64 için OrderAccess: release_store_fence, xchg komutunu kullanarak tanımlanır.

Jdk7'de tam olarak nasıl tanımlandığını görebilirsiniz (doug lea, JDK 8 için bazı yeni şeyler üzerinde çalışıyor): http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/ linux_x86 / vm / orderAccess_linux_x86.inline.hpp

lazySet kodunun derlemesini çalışırken sökmek için hdis'i de kullanabilirsiniz.

Bununla ilgili başka bir soru daha var: xchg kullanırken mfence'e ihtiyacımız var mı


5
Burada ne elde ettiğinizi anlamak zor. Lütfen fikrinizi açıklar mısınız?
Paul Bellora

3
x86 (x86_64) üzerinde "lazySet == unsafe.putOrderedLong == xchg rw (nehelem intel cpu üzerinde 20 çevrime mal olan bir yumuşak bariyer görevi gören asm talimatı) böyle bir engel, volatile veya AtomicLong getAndAdd'den çok daha ucuz performans açısından daha ucuzdur" -> Bu, bildiğim kadarıyla doğru değil. lazySet / putOrdered, bir adrese giden bir MOV'dur, bu nedenle JMM yemek kitabı onu x86'da işlemsiz olarak tanımlar.
Nitsan Wakart

11

LazySet'in kökenleri ve faydası hakkında daha geniş bir tartışma ve temel alınan putOrdered burada bulunabilir: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html

Özetlemek gerekirse: lazySet, bir mağaza yükü çiti değil, bir mağaza-mağaza görevi görmesi açısından zayıf uçucu bir yazmadır. Bu, geçici bir küme için kullanılan önemli ölçüde daha pahalı talimat yerine, derleyici tarafından yeniden sıralanamayan bir MOV talimatına derlenen JIT olan lazySet'e indirgenir.

Değeri okurken her zaman geçici bir okuma yaparsınız (her durumda bir Atomic * .get () ile).

lazySet, tek bir yazıcıya tutarlı bir geçici yazma mekanizması sunar, yani tek bir yazarın bir sayacı artırmak için lazySet'i kullanması tamamen meşrudur, aynı sayacı artıran birden çok iş parçacığı, CAS kullanarak rakip yazma işlemlerini çözmek zorunda kalacaktır; incAndGet için Atomic * 'in kapakları.


Tam olarak, neden bu basit olduğunu söyleyemeyiz StoreStorebariyer, ama değil bir StoreLoad?
Eugene

8

Gönderen Eşzamanlı-atom paket özet

lazySet , kendileri geçici olmayan yazma işlemleriyle yeniden sıralama kısıtlamaları empoze etmeyen sonraki (ancak daha önce değil) bellek eylemleriyle yeniden sıralamalara izin vermesi dışında, geçici bir değişken yazma (atama) gibi bellek etkilerine sahiptir. Diğer kullanım bağlamlarının yanı sıra, lazySet, bir daha asla erişilemeyen bir başvuru olan çöp toplama uğruna boş bırakılırken uygulanabilir.

LazySet'i merak ediyorsanız, kendinize başka açıklamalar da borçlusunuz.

Atomik erişim ve güncellemeler için hafıza efektleri, Java ™ Dil Spesifikasyonu bölüm 17.4'te belirtildiği gibi genellikle uçucu maddeler için kuralları izler.

get uçucu bir değişkeni okumanın bellek etkilerine sahiptir.

set , bir uçucu değişken yazma (atama) gibi bellek etkilerine sahiptir.

lazySet , kendileri geçici olmayan yazma işlemleriyle yeniden sıralama kısıtlamaları empoze etmeyen sonraki (ancak daha önce değil) bellek eylemleriyle yeniden sıralamalara izin vermesi dışında, geçici bir değişken yazma (atama) gibi bellek etkilerine sahiptir. Diğer kullanım bağlamlarının yanı sıra, lazySet, bir daha asla erişilemeyen bir başvuru olan çöp toplama uğruna boş bırakılırken uygulanabilir.

zayıfCompareAndSet , bir değişkeni atomik olarak okur ve koşullu olarak yazar, ancak herhangi bir sıralamadan önce meydana gelmez, bu nedenle zayıfCompareAndSet hedefi dışındaki herhangi bir değişkenin önceki veya sonraki okuma ve yazma işlemlerine ilişkin hiçbir garanti sağlamaz.

CompareAndSet ve getAndIncrement gibi diğer tüm okuma ve güncelleme işlemleri, uçucu değişkenleri okuma ve yazma gibi bellek etkilerine sahiptir.


4

İşte anlayışım, yanılıyorsam düzeltin: lazySet()"Yarı" uçucu olarak düşünebilirsiniz : temelde diğer evreler tarafından okunması açısından uçucu olmayan bir değişkendir, yani lazySet tarafından ayarlanan değer başkaları tarafından görülmeyebilir İş Parçacığı. Ancak başka bir yazma işlemi gerçekleştiğinde uçucu hale gelir (diğer iş parçacıklarından olabilir). LazySet'in hayal edebileceğim tek etkisi compareAndSet. Dolayısıyla, kullanırsanız lazySet(), get()diğer evrelerden eski değeri almaya devam edebilir, ancak compareAndSet()bu bir yazma işlemi olduğundan her zaman yeni değere sahip olacaktır.


1
değil compareAndSetmi
Dave Moten

2

Re: kısaltmaya çalışın -

Bunu, geçici bir alanı belirli bir depo (örneğin: ref = null;) işlemi için geçici değilmiş gibi ele almanın bir yolu olarak düşünebilirsiniz.

Bu tam olarak doğru değil, ancak "Tamam, gerçekten umrumda değil" ve "Hmm, bunu biraz düşüneyim" arasında bir karar vermeniz yeterli olmalı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.