Tento článok je zrkadlovým článkom o strojovom preklade, kliknite sem pre prechod na pôvodný článok.

Pohľad: 46741|Odpoveď: 7

[Zdroj] Volatile vs. Interlocked vs. lock

[Kopírovať odkaz]
Zverejnené 27. 8. 2018 14:40:35 | | |
Povedzme, že existuje trieda, ktorá obsahuje verejné pole čítača int, ku ktorému môže pristupovať viacero vlákien, a toto číslo sa bude len zvyšovať alebo znižovať.

Pri pridávaní tohto poľa, ktoré z nasledujúcich schém by sa mali použiť a prečo?

  • lock(this.locker) this.counter++;
  • Interlocked.Increment (ref this.counter);
  • Zmeňte modifikátor prístupu z counter na verejný volatile


Najhoršie (žiadny z nich vlastne nefunguje)

Zmeňte modifikátor prístupu z counter na verejný volatile

Tento prístup v skutočnosti vôbec nie je bezpečný a pointa volatile je, že viaceré vlákna bežiace na viacerých CPU ukladajú dáta do vyrovnávacej pamäte a preskupujú vykonané inštrukcie.

Ak je nevolatilný, keď CPU A vzrastie o hodnotu, CPU B musí chvíľu počkať, kým sa hodnota zvýši, čo môže viesť k problémom.

Ak je to volatilné, zabezpečuje to, že oba CPU vidia rovnakú hodnotu súčasne. Ale nevyhne sa krížovým operáciám čítania a zápisu.

Pridanie hodnoty k premennej v skutočnosti zahŕňa tri kroky

1. Čítanie, 2. Pridaj 3. Píš

Predpokladajme, že vlákno A číta hodnotu čítača ako 1 a nie je pripravené na zvýšenie, potom vlákno B tiež číta hodnotu čítača ako 1, a potom obe vlákna začnú vykonávať inkrementálne a zápisné operácie. Hodnota posledného čítača je 2. To nie je správne, obe vlákna vykonali operáciu zvyšovania a správny výsledok by mal byť 3. Takže označovať ho za nestály je jednoducho nebezpečné.

Je to lepšie

lock(this.locker) this.counter++;

Takto je to bezpečné (samozrejme, nezabudnite zamknúť všade, kde chcete pristupovať k tomuto pultu). Zabráni akémukoľvek inému vláknu vykonať uzamknutý kód. A tiež zabraňuje problému sekvencovania inštrukcií s viacprocesormi, ktorý bol spomenutý vyššie. Problém je, že zámok je pomalý vo výkone, a ak použijete zámok na iných nesúvisiacich miestach, môže zablokovať vaše ostatné vlákna.

Najlepšie

Interlocked.Increment (ref this.counter);

Je to bezpečné a veľmi efektívne. Vykonáva čítanie, zvyšovanie a zápis troch operácií v jednom atóme bez prerušenia v strede. Keďže to neovplyvňuje iný kód, nemusíš si pamätať zámky inde. A je to tiež veľmi rýchle (ako MSDN hovorí, na dnešných CPU je to často len inštrukcia).

Ale nie som si úplne istý, či to dokáže vyriešiť aj problém s poradím inštrukcií CPU, alebo či je potrebné ho používať spolu s Volatile a týmto inkrementom.

Doplnok: Aké problémy Volatile rieši dobre?

Keďže Volatile nemôže zabrániť multithreadingu, čo dokáže? Dobrým príkladom sú dve vlákna, jedno vždy zapisuje do premennej, povedzme, že táto premenná je queneLength, a druhé vždy číta dáta z tejto premennej. Ak dĺžka queueLongt nie je volatilná, vlákno A môže čítať 5-krát, ale vlákno B môže vidieť oneskorené dáta alebo dokonca údaje v nesprávnom poradí. Jedným riešením je použiť zámok, ale v tomto prípade môžete použiť aj volatile. To zabezpečuje, že vlákno B vždy vidí najnovšie dáta zapísané vláknom A, ale táto logika funguje len vtedy, ak ich nečítate pri písaní a ak ich nezapisujete pri čítaní. Keď chce viacero vlákien vykonávať operácie čítania, úpravy-zápisu, musíte použiť Interlocked alebo lock.





Predchádzajúci:Šifrovacia metóda Java MD5
Budúci:Linq implementuje nie v a v podmienených dotazoch v SQL
Zverejnené 29. 8. 2018 16:21:42 |
Ahoj, ten kód, ktorý si urobil skôr, ktorý kombinuje highcharty stacked histogramy a drillable histogramy? Chcel by som sa opýtať, či môžete poslať kód, ktorý sa dá upraviť na rozhraní https://jshare.com.cn/demos/hhhhDz?hc-theme=grid-light?
Zverejnené 29. 8. 2018 16:22:13 |
Celá sieť je len váš zdroj.
Zverejnené 29. 8. 2018 16:22:55 |
Pretože predchádzajúcich 90 rokov nedokázalo zanechať odkaz. takže
Zverejnené 29. 8. 2018 16:40:40 |
Je pohodlné pridať kontaktné údaje? Poradiť sa s tebou
 Prenajímateľ| Zverejnené 15. 9. 2018 13:10:16 |
súkromný statický int safeInstanceCount = 0; Pracovať s atómami
System.Threading.Interlocked.Increment(ref safeInstanceCount); Samo-zvyšovanie 1
System.Threading.Interlocked.Decrement(ref safeInstanceCount); Self-mínus 1
Zverejnené 21. 5. 2020 16:43:54 |
Podporte vlastníka pri zdieľaní
 Prenajímateľ| Zverejnené 11. 6. 2020 15:00:16 |
1. Koncept

V prostredí s viacvláknovým prostredím operácie, ktoré nie sú prerušované mechanizmami plánovania vlákien; Keď táto operácia začne, beží až do konca, bez akéhokoľvek prepínania kontextu (prepínania na iné vlákno) medzi tým.

2. Trieda

System.Threading.Interlocked statická trieda

3. Bežne používané funkcie (pozri ostatné)

1. verejný statický in-dekrement (referencia int location); Decrinujte hodnotu špecifikovanej premennej vo forme atómovej operácie a uložte výsledok

Ekvivalent lock(obj){i--; }

2. verejný statický inkrement (referencia int location); Zvyšujte hodnotu špecifikovanej premennej vo forme atómovej operácie a uložte výsledok

Ekvivalent lock(obj){i++; }
Vyhlásenie:
Všetok softvér, programovacie materiály alebo články publikované spoločnosťou Code Farmer Network slúžia len na vzdelávacie a výskumné účely; Vyššie uvedený obsah nesmie byť použitý na komerčné alebo nezákonné účely, inak nesú všetky následky používateľmi. Informácie na tejto stránke pochádzajú z internetu a spory o autorské práva s touto stránkou nesúvisia. Musíte úplne vymazať vyššie uvedený obsah zo svojho počítača do 24 hodín od stiahnutia. Ak sa vám program páči, podporte originálny softvér, zakúpte si registráciu a získajte lepšie originálne služby. Ak dôjde k akémukoľvek porušeniu, kontaktujte nás prosím e-mailom.

Mail To:help@itsvse.com