Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 46741|Răspunde: 7

[Sursă] Volatil vs. Interblocat vs. încuietoare

[Copiază linkul]
Postat pe 27.08.2018 14:40:35 | | |
Să presupunem că există o clasă care conține un câmp public int counter accesibil de mai multe fire de execuție, iar acest număr va crește sau scădea doar.

La adăugarea acestui câmp, care dintre următoarele scheme ar trebui folosite și de ce?

  • lock(this.locker) this.counter++;
  • Interlocked.Increment(ref this.counter);
  • Schimbă modificatorul de acces al contorului la volatil public


Cel mai rău (niciunul dintre ele nu funcționează cu adevărat)

Schimbă modificatorul de acces al contorului la volatil public

Această abordare nu este deloc sigură, iar ideea despre volatile este că mai multe fire care rulează pe mai multe procesoare stochează datele și rearanjează instrucțiunile executate.

Dacă este non-volatil, când CPU-ul A crește cu o valoare, CPU-ul B trebuie să aștepte ceva timp pentru a vedea valoarea crescută, ceea ce poate duce la probleme.

Dacă este volatil, asigură că ambele procesoare văd aceeași valoare în același timp. Dar nu evită operațiunile de citire și scriere transversale.

Adăugarea de valoare unei variabile implică de fapt trei pași

1. Citit, 2. Adaugă 3. Scrie

Să presupunem că firul A citește valoarea contorului ca 1 și nu este pregătit să crească, atunci firul B citește de asemenea valoarea contorului ca 1, iar ambele fire încep să efectueze operații incrementale și de scriere. Valoarea contorului final este 2. Acest lucru nu este corect, ambele fire au făcut o operație de creștere, iar rezultatul corect ar trebui să fie 3. Așadar, etichetarea lor ca fiind volatilă este pur și simplu nesigură.

E mai bine

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

Astfel este sigur (amintește-ți să încuii oriunde vrei să accesezi acest cont, desigur). Împiedică orice alt fir de execuție codul blocat. Și previne și problema secvențierii instrucțiunilor multi-CPU menționată mai sus. Problema este că blocarea are performanță lentă, iar dacă folosești blocarea în alte locuri fără legătură, poate bloca celelalte fire de execuție.

Cele mai bune

Interlocked.Increment(ref this.counter);

Este sigur și foarte eficient. Efectuează citire, creștere, scriere a trei operații într-un atom fără a fi întrerupt la mijloc. Pentru că nu afectează alte coduri, nu trebuie să-ți amintești lacătele din alte părți. Și este, de asemenea, foarte rapid (așa cum spune MSDN, pe procesoarele de azi, este adesea doar o instrucțiune).

Dar nu sunt complet sigur dacă poate rezolva și problema ordinii instrucțiunilor a CPU-ului sau dacă trebuie folosit împreună cu volatile și această creștere.

Supliment: Ce probleme rezolvă bine volatilele?

Deoarece volatilul nu poate preveni multithreading-ul, ce poate face? Un exemplu bun este că ai două fire, unul scrie întotdeauna pe o variabilă, să zicem că această variabilă este queneLength, iar celălalt citește întotdeauna datele de la această variabilă. Dacă lungimea cozii nu este volatilă, firul A poate citi de 5 ori, dar firul B poate vedea date întârziate sau chiar date în ordinea greșită. O soluție este să folosești blocare, dar în acest caz poți folosi și volatile. Acest lucru asigură că firul B vede întotdeauna cele mai recente date scrise de firul A, dar această logică funcționează doar dacă nu le citești când le scrii și dacă nu le scrii când le citești. Odată ce mai multe fire vor să facă operații de citire-modificare-scriere, trebuie să folosești Interlocked sau lock.





Precedent:Metoda de criptare Java MD5
Următor:Linq implementează interogări condiționate în și nu în SQL
Postat pe 29.08.2018 16:21:42 |
Salut, codul pe care l-ai făcut mai devreme care combină highcharts, histograme stivuite și histograme forabile? Aș dori să întreb dacă poți trimite un cod care poate fi editat pe interfața https://jshare.com.cn/demos/hhhhDz?hc-theme=grid-light?
Postat pe 29.08.2018 16:22:13 |
Întreaga rețea este doar resursa ta.
Postat pe 29.08.2018 16:22:55 |
Pentru că ultimii 90 de ani nu puteau lăsa niciun mesaj. deci
Postat pe 29.08.2018 16:40:40 |
Este convenabil să adaugi o informație de contact? Consultări cu tine
 Proprietarul| Postat pe 15.09.2018 13:10:16 |
private static int safeInstanceCount = 0; Operează cu atomi
System.Threading.Interlocked.Increment(ref safeInstanceCount); Auto-creștere 1
System.Threading.Interlocked.Decrement(ref safeInstanceCount); Auto-minus 1
Postat pe 21.05.2020 16:43:54 |
Susține proprietarul să împartă
 Proprietarul| Postat pe 11.06.2020 15:00:16 |
1. Concept

Într-un mediu multi-threaded, operațiunile care nu sunt întrerupte de mecanismele de programare a firelor de execuție; Odată ce această operație începe, rulează până la final, fără niciun schimb de context (schimbarea la un alt fir) între ele.

2. Clasă

Clasa statică System.Threading.Interlocked

3. Funcții utilizate frecvent (vezi restul)

1. static public int Decrement(ref int location); Reduci valoarea variabilei specificate sub forma unei operații atomice și stochează rezultatul

Echivalent cu lock(obj){i--; }

2. static public int Increment(ref int location); Se incrementează valoarea variabilei specificate sub forma unei operații atomice și se stochează rezultatul

Echivalent cu lock(obj){i++; }
Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com