Kada upotrijebiti hlapljivu ključnu riječ u C #

Tehnike optimizacije koje koristi JIT (just-in-time) kompajler u Common Language Runtimeu mogu dovesti do nepredvidivih rezultata kada vaš .Net program pokušava izvoditi nestalna čitanja podataka u višenitnom scenariju. U ovom ćemo članku pogledati razlike između hlapljivog i trajnog pristupa memoriji, ulogu volatilne ključne riječi u C # i kako treba koristiti volatilnu ključnu riječ.

Dati ću nekoliko primjera koda u C # za ilustraciju koncepata. Da bismo razumjeli kako hlapljiva ključna riječ radi, prvo moramo razumjeti kako strategija optimizacije JIT kompajlera djeluje u .Net-u.

Razumijevanje optimizacija JIT kompajlera

Treba imati na umu da će JIT kompajler, kao dio strategije optimizacije, promijeniti redoslijed čitanja i pisanja na način koji neće promijeniti značenje i konačni izlaz programa. To je prikazano u isječku koda koji je dan u nastavku.

x = 0;

x = 1;

Gornji isječak koda može se promijeniti u sljedeći - uz očuvanje izvorne semantike programa.

x = 1;

Prevodnik JIT također može primijeniti koncept nazvan "konstantno širenje" za optimizaciju sljedećeg koda.

x = 1;

y = x;

Gornji isječak koda može se promijeniti u sljedeći - opet uz očuvanje izvorne semantike programa.

x = 1;

y = 1;

Hlapljiv naspram trajnog pristupa memoriji

Memorijski model suvremenih sustava prilično je složen. Imate registre procesora, različite razine predmemorije i glavnu memoriju koju dijeli više procesora. Kada se vaš program izvrši, procesor može predmemorirati podatke, a zatim pristupiti tim podacima iz predmemorije kada to zatraži izvršna nit. Ažuriranja i čitanja ovih podataka mogu se pokretati u skladu s predmemoriranom verzijom podataka, dok se glavna memorija ažurira kasnije. Ovaj model korištenja memorije ima posljedice za višenitne aplikacije. 

Kada jedna nit komunicira s podacima u predmemoriji, a druga nit istodobno pokušava pročitati iste podatke, druga nit može čitati zastarjelu verziju podataka iz glavne memorije. To je zato što se kada se ažurira vrijednost trajnog objekta, promjena se vrši u predmemoriji izvršne niti, a ne u glavnoj memoriji. Međutim, kada se vrijednost hlapljivog objekta ažurira, ne samo da se vrši promjena u predmemoriji izvršne niti, već se ta predmemorija ispire u glavnu memoriju. A kad se pročita vrijednost volatilnog objekta, nit osvježava svoju predmemoriju i čita ažuriranu vrijednost.

Korištenje volatile ključne riječi u C #

Hlapljiva ključna riječ u C # koristi se za obavještavanje JIT sastavljača da vrijednost varijable nikada ne smije biti u predmemoriji, jer bi je mogao promijeniti operativni sustav, hardver ili istodobno izvršavajuća nit. Prevoditelj tako izbjegava bilo kakvu optimizaciju varijable koja bi mogla dovesti do sukoba podataka, tj. Do različitih niti koje pristupaju različitim vrijednostima varijable.

Kad objekt ili varijablu označite kao hlapljive, ona postaje kandidat za volatilno čitanje i pisanje. Treba imati na umu da su u C # sva upisivanja u memoriju volatilna, bez obzira pišete li podatke u volatilni ili nehlapni objekt. Međutim, dvosmislenost se događa kada čitate podatke. Kada čitate podatke koji nisu hlapljivi, izvršavajuća nit može ili ne mora uvijek dobiti najnoviju vrijednost. Ako je objekt hlapljiv, nit uvijek dobiva najnoviju vrijednost.

Varijablu možete proglasiti nestabilnom tako što ćete joj dodati volatileključnu riječ. Sljedeći isječak koda to ilustrira.

razredni program

    {

        javno nestabilno int i;

        statička praznina Main (string [] args)

        {

            // Ovdje napišite svoj kod

        }

    }

volatileKljučnu riječ možete koristiti s bilo kojom vrstom reference, pokazivača i nabrajanja. Također možete koristiti hlapljivi modifikator s bajtnim, kratkim, int, char, float i bool vrstama. Treba imati na umu da se lokalne varijable ne mogu deklarirati kao hlapljive. Kada odredite objekt referentnog tipa kao volatilni, samo je pokazivač (32-bitni cijeli broj koji pokazuje na mjesto u memoriji gdje je objekt zapravo pohranjen) volatilan, a ne vrijednost instance. Također, dvostruka varijabla ne može biti hlapljiva jer je velika 64 bita, veća od veličine riječi na x86 sustavima. Ako trebate napraviti dvostruku varijablu hlapljivo, trebali biste je umotati u nastavu. To možete učiniti jednostavno stvaranjem klase omota kao što je prikazano u isječku koda u nastavku.

javna klasa VolatileDoubleDemo

{

    private volatile WrappedVolatileDouble volatileData;

}

javna klasa WrappedVolatileDouble

{

    javni dvostruki podaci {get; postavljen; }

Međutim, imajte na umu ograničenje gornjeg primjera koda. Iako biste imali najnoviju vrijednost volatileDatareferentnog pokazivača, nije vam zajamčena najnovija vrijednost Datasvojstva. Oko toga se radi na tome da se WrappedVolatileDoubletip učini nepromjenjivim.

Iako vam hlapljiva ključna riječ može pomoći u sigurnosti niti u određenim situacijama, ona nije rješenje za sve probleme s istodobnošću niti. Trebali biste znati da označavanje varijable ili objekta volatilnim ne znači da ne trebate koristiti ključnu riječ lock. Hlapljiva ključna riječ nije zamjena za ključnu riječ lock. Jedino je tu da vam pomogne izbjeći sukobe podataka kada imate više niti koje pokušavaju pristupiti istim podacima.