Artık görüşmeyi yapan kişiden korkmayın, sorunlu noktaya gelin ve geçici anahtar kelimeyi anlayın, böylece görüşme kolayca geçebilir

Önsöz

İnternet şirketlerinin yükselişiyle, teknolojimiz için gereksinimler gittikçe artmaktadır.Çoğu zaman şirketler, paradan tasarruf etmek ve makinelerinin performansını en üst düzeye çıkarmak istemektedir, bu da programcıları gerçekten tüketir.

Elbette, toplumun ilerlemesine uyum sağlamak istiyorsanız, programcıların sürekli kendilerini yenilemeleri gerekir, ancak insanlar köklerini unutabilir ve temel bilgileri öğrenebilir.

Hayır, sınıf arkadaşlarımdan biri şikayet etmek için bana geldi İlk iki görüşme sorunsuz geçti ve üç tarafa geçici anahtar kelime yerleştirildi.

Uçucu hakkında konuşalım

uçucu

Uçucu bir tür değiştiricidir. Volatile işlevi, derleyici optimizasyonu nedeniyle bu talimatın atlanmamasını sağlamak için bir talimat anahtar sözcüğü olarak kullanılacaktır.

Uçucunun özellikleri

  • Bu, bu değişken üzerinde çalışan farklı evrelerin görünürlüğünü sağlar, yani bir iş parçacığı bir değişkenin değerini değiştirirse, yeni değer hemen diğer iş parçacıkları tarafından görülebilir. (Görünürlük elde edin)
  • Talimatların yeniden sıralanması yasaktır. (Düzeni anlayın)
  • Uçucu, yalnızca tek bir okuma / yazmanın atomikliğini garanti edebilir. i ++ Bu işlem atomikliği garanti edemez.

Uçucu atomikliğe ilişkin olarak, uçucu bir değişkenin tek bir okuma / yazma işleminin, aşağıdaki SoWhat ve SynSoWhat fonksiyonlarına benzer şekilde, bu tekli okuma / yazma işlemlerini senkronize etmek için aynı kilidi kullandığı kabul edilebilir.

class SoWhat { uçucu int i = 0; // uçucu değiştirilmiş değişken public int getI () { return i; // Tek bir uçucu değişkenin okunması } public void setI (int j) { this.i = j; // tek bir uçucu değişken yazın } public void inc () { i ++; // Birden çok uçucu değişkeni birleştirin } } class SynSoWhat { int i = 0; genel senkronize int getI () { dönüş i; } genel senkronize edilmiş void setI (int j) { this.i = j; } public void inc () {// sıradan yöntem çağrısı int tmp = getI (); // senkronize edilmiş yöntemi çağırın tmp = tmp + 1; // Yaygın yazma yöntemi setI (tmp); // Eşitlenmiş yöntemi çağırın } }

Anlama yazın

Volatile tarafından yazılan bellek semantiği aşağıdaki gibidir:

Uçucu bir değişken yazarken, JMM, iş parçacığına karşılık gelen yereldeki paylaşılan değişkenin değerini ana belleğe temizleyecektir.

public class VolaSemanteme { int a = 0; uçucu boole bayrağı = false; // Nokta budur public void init () { a = 1; bayrak = doğru; // ....... } genel geçersiz kullanım () { if (bayrak) { int i = a * a; } // ....... } }

İş Parçacığı A, init yöntemini çağırır ve iş parçacığı B, kullanım yöntemini çağırır.

Okuduğunu anlama

Uçucu okumanın bellek semantiği aşağıdaki gibidir:

Uçucu bir değişkeni okurken, JMM iş parçacığına karşılık gelen yerel belleği geçersiz kılar. İş parçacığı daha sonra paylaşılan değişkeni ana bellekten okuyacaktır.

public class VolaSemanteme {

int a = 0;

uçucu boole bayrağı = false; // Nokta budur

public void init () {

a = 1;

bayrak = doğru;

// .......

}

genel geçersiz kullanım () {

if (bayrak) {

int i = a * a;

}

// .......

}

}

Akış şeması kabaca şu şekildedir:

uçucu talimat yeniden düzenlemesi

Uçucu değişkenlerin bellek görünürlüğü bellek engeline (Bellek Bariyeri) bağlıdır. Bellek engeli ile ilgili özel açıklama daha önce yazılmıştır ve tekrarlanmayacaktır.JMM kurulumu görünmez olmaya zorlanmıştır. Özetle, JMM içinde talimat yeniden düzenlemesi olacak ve talimat yeniden düzenlemesinin doğruluğunu sağlamak için af-if-serial ve-önce-gerçekleşmesi kavramları olacaktır. Bellek bariyeri, 4 montaj düzeyinde anahtar kelimeye dayalı talimatların yeniden düzenlenmesini yasaklar. Uçucu madde için yeniden düzenleme kuralları aşağıdaki gibidir:

  • İlki bir okuma işlemi olduğunda, ikincinin herhangi bir işlemi birinciden önce yeniden sıralanamaz.
  • İkincisi bir yazma işlemi olduğunda, birinci işlemin herhangi bir işlemi ikinciden sonra yeniden sıralanamaz.
  • Birincisi bir yazma işlemi olduğunda, ikinci okuma ve yazma işlemi yeniden sıralama yapmaz.

uçucu yazma düşük seviyeli uygulama

JMM'nin geçici için bellek engeli ekleme stratejisi

Her geçici yazma işleminden önce bir StoreStore bariyeri ekleyin. Her geçici yazma işleminden sonra bir StoreLoad bariyeri yerleştirin.

uçucu okuma alt katman uygulaması

JMM'nin geçici için bellek engeli ekleme stratejisi

Her uçucu okuma işleminden sonra bir LoadLoad bariyeri yerleştirin. Her uçucu okuma işleminden sonra bir LoadStore bariyeri yerleştirin.

Odak noktası, neden bir LoadLoad'un ardından değişken bir okuma olduğudur. Ekleme İki AB iş parçacığı tarafından yürütülecek aşağıdaki koda sahibim ve B iş parçacığının bayrağı aşağıdaki okumayı alır gelişmiş.

Uçucu gerçekleşme ilkesi

Uçucu değişkenlerle değiştirilen paylaşılan değişkenler, işlemleri yazarken CPU tarafından sağlanan Kilit önek talimatını kullanır. CPU seviyesindeki işlevler aşağıdaki gibidir:

Mevcut işlemci önbellek hattının verilerini sistem belleğine geri yaz

Belleğe geri yazma işlemi, diğer CPU'larda aldığınız değişkenlerin geçersiz olduğunu ve bir dahaki sefere kullandığınızda belleği yeniden paylaşmanız gerektiğini söyleyecektir.

Basit kodun ayrıntılı demontajına jitwatch üzerinden bakabiliriz.

package com.sowhat.demo; public class VolaSemanteme { int unvloatileVal = 0; uçucu boole bayrağı = yanlış; public void init () { unvloatileVal = 1; flag = true; // Dokuzuncu satır } genel geçersiz kullanım () { if (bayrak) { int LocalA = unvloatileVal; eğer (LocalA == 0) { yeni RuntimeException ("hata") atar; } } } public static void main (String args) { VolaSemanteme volaSemanteme = new VolaSemanteme (); volaSemanteme.init (); volaSemanteme.use (); } }

Sıradan değişkenlere atama işlemleri:

Uçucu değişkenlere atama işlemleri.

Karşılaştırılabilir, uçucu tarafından modifiye edilen değişken gerçekten de bir tane daha kilit eklentisine sahip olacaktır $ 0x0, (% rsp) komutu.

0x0000000114ce95cb: eklentiyi kilitle $ 0x0, (% rsp); * putfield bayrağı ; -com.sowhat.demo.VolaSemanteme :: init @ 7 (satır 9)

Uçucu uygulama senaryoları

Uçucu kullanmak için ön koşullar

  • Değişkene yazma işlemi mevcut değere bağlı değildir.
  • Bu değişken, diğer değişkenlerle birlikte değişmez.

Uçucu, yalnızca durum programdaki diğer içerikten gerçekten bağımsız olduğunda kullanılabilir.

Durum bayrağı

Belki de uçucu değişkenlerin kanonik kullanımı, başlatmanın tamamlanması veya kapatma talebi gibi önemli bir kerelik olayın gerçekleştiğini belirtmek için basit bir mantıksal durum bayrağının kullanılmasıdır.

volatile boolean shutdownRequested; ...... public void shutdown () {shutdownRequested = true;} public void doWork () { while (! shutdownRequested) { // şeyler yapmak } }

Tek seferlik güvenli yayın

Senkronizasyon eksikliği, görünürlüğü imkansız hale getirebilir, bu da orijinal değer yerine bir nesne referansının ne zaman yazılacağını belirlemeyi zorlaştırır. Senkronizasyonun yokluğunda, bir nesne referansının güncellenmiş değeri (başka bir evre tarafından yazılan) ve nesnenin durumunun eski değeri aynı anda var olabilir. (Bu, nesne referanslarının senkronizasyon olmadan okunduğu, iyi bilinen çift işaretli kilitleme sorununun temel nedenidir. Sorun, güncellenmiş bir referans görebilmenizdir, ancak Bu referans aracılığıyla eksik yapılandırılmış nesneleri görün).

public class BackgroundFloobleLoader { halka açık uçucu Flooble theFlooble; public void initInBackground () { // çok şey yap theFlooble = new Flooble (); // bu Flooble'a yazılan tek şeydir } } public class SomeOtherClass { public void doWork () { while (true) { // bir şeyler yapalım ... // Flooble'ı kullanın, ancak yalnızca hazırsa eğer (floobleLoader.theFlooble! = null) doSomething (floobleLoader.theFlooble); } } }

Bağımsız gözlem

Uçucunun güvenli kullanımının bir başka basit modu, programda dahili kullanım için düzenli olarak gözlemler yayınlamaktır. Örneğin, ortam sıcaklığını algılayabilen bir ortam sensörü olduğunu varsayalım. Bir arka plan dizisi, sensörü birkaç saniyede bir okuyabilir ve geçerli belgeyi içeren uçucu değişkeni güncelleyebilir. Ardından, diğer ipler bu değişkeni okuyabilir, böylece herhangi bir zamanda en son sıcaklık değerini görebilirler.

public class UserManager { public volatile String lastUser; public boolean authentication (String kullanıcısı, String şifresi) { boolean geçerli = passwordIsValid (kullanıcı, parola); eğer (geçerli) { Kullanıcı u = yeni Kullanıcı (); activeUsers.add (u); lastUser = kullanıcı; } geçerli dönüş; } }

uçucu fasulye deseni

Uçucu fasulye modelinde, JavaBean'ın tüm veri üyeleri uçucu tiptedir ve alıcı ve ayarlayıcı yöntemleri çok yaygın olmalıdır - karşılık gelen özellikleri almak veya ayarlamak dışında herhangi bir mantık içeremezler. Ek olarak, bir nesne tarafından referans verilen veri üyeleri için, referans verilen nesnenin etkili bir şekilde değişmez olması gerekir. (Bu, dizi değerlerine sahip öznitelikleri engeller, çünkü bir dizi başvurusu uçucu olarak bildirildiğinde, dizinin kendisi değil, yalnızca başvuru, uçucu anlamlara sahiptir). Herhangi bir uçucu değişken için, değişmezler veya kısıtlar JavaBean özelliklerini içeremez.

@Hayalhanemersin public class Person { özel uçucu String firstName; özel uçucu String lastName; özel değişken int yaş; public String getFirstName () {return firstName;} public String getLastName () {return lastName;} public int getAge () {dönüş yaşı;} public void setFirstName (String firstName) { this.firstName = firstName; } public void setLastName (String lastName) { this.lastName = lastName; } public void setAge (int age) { this.age = yaş; } }

Düşük maliyetli okuma-yazma kilidi stratejisi

Uçucunun işlevi bir sayaç uygulamak için yeterli değildir. ++ x aslında üç işlemin basit bir birleşimidir (okuma, ekleme, saklama), birden fazla iş parçacığı aynı anda değişken sayacı artırmaya çalışırsa, güncel değeri kaybolabilir. Okuma işlemleri yazma işlemlerini çok aşarsa, ortak kod yolunun ek yükünü azaltmak için dahili kilitler ve geçici değişkenler birleştirilebilir. Güvenli sayaç, artırma işleminin atomik olmasını sağlamak için senkronize edilmiş kullanır ve mevcut sonucun görünürlüğünü sağlamak için uçucu kullanır. Güncelleme sık değilse, bu yöntem daha iyi performans sağlayabilir, çünkü okuma yolunun maliyeti yalnızca geçici okuma işlemlerini içerir ve bu genellikle çekişmesiz bir kilit edinme maliyetinden daha iyidir.

@Hayalhanemersin public class CheesyCounter { // Ucuz okuma-yazma kilidi hilesi kullanır // Tüm mutatif işlemler 'bu' kilit tutularak YAPILMALIDIR @GuardedBy ("bu") özel uçucu int değeri; public int getValue () {dönüş değeri;} genel senkronize int artışı () { dönüş değeri ++; } }

Çifte kontrol

Tekli modun bir uygulaması, ancak birçok kişi uçucu anahtar kelimeyi görmezden gelecektir, çünkü bu anahtar kelime olmadan program da çok iyi çalışabilir, ancak kodun kararlılığı her zaman% 100 olmayabilir, belki gelecekte O anda gizli böcek çıktı.

sınıf Singleton { özel uçucu statik Singleton örneği; public static Singleton getInstance () { eğer (örnek == null) { syschronized (Singleton.class) { eğer (örnek == null) { örnek = new Singleton (); } } } dönüş örneği; } }

Geç yüklemenin zarif yolu önerilir: Talep Tutucusunda Başlatma (IODH).

public class Singleton { statik sınıf SingletonHolder { statik Singleton örneği = new Singleton (); } public static Singleton getInstance () { SingletonHolder.instance döndür; } }
Rus matematikçi şunu önerdi: "Paralel çizgiler kesişebilir", ancak alay konusu oldu ve ölümünden 12 yıl sonra kanıtlandı
önceki
Paylaş: Tanıdık MVC tasarım modeli ve üç katmanlı mimari hakkında konuşun
Sonraki
JDK, JRE ve JVM'nin ne olduğunu ve aralarındaki ilişkiyi bilmek ister misiniz?
Programcı: Son zamanlarda iş parçacığı güvenliği ve performans arasındaki dengeyi düşünüyordum
Gelişmiş Paylaşım: Java multithreading'i gerçekten anlıyor musunuz? Sizi bir kez çoklu iş parçacığı oynamaya götürür!
İş arkadaşları eşzamanlılığın zor olduğunu söylüyor, Java eşzamanlılığı da öyle mi? Eşzamanlılık mekanizmasının altında yatan üç ilke
Programcı: Çok iş parçacıklı paylaşılan kaynak senkronizasyonu, dikkatli bakmazsanız pişman olacaksınız
Programcı: İş parçacığını nasıl doğru bir şekilde durduracağınızı hala bilmiyor musunuz?
İyi makale paylaşımı: JavaWeb'de size yönetici oturum açma bilgilerini ve CURD bilgilerini göstermek için 5 resim
Programcı: Nesnenin özünü ortaya çıkarmak için Java'nın 5 özelliği
Çin'in bilim ve teknolojisinin bir başka güzel haberi daha var, kuantum çip teknolojik sınırı aşıyor ve dünya hemen köşede!
Maskeyi litografi makinesi ile değiştirin! Hollanda kontrolden çıktı ve yardım istiyor, Rusya: Çin'in büyük bir fırsatı var
Uyarılmış! Çin bağımsız olarak gelecekte artık kısıtlanmayacak bir "kuantum çipi" geliştirdi
14nm işleminin seri üretiminin ardından, Çin'in çipi 6nm'lik buz darboğazını kırarak başka bir iyi habere sahip
To Top