Hver er munurinn á þráðlausu og atómlegu?


svara 1:

Thread-safe þýðir að það eru engin vandamál þegar aðgangur er að mörgum þræði. Atóm þýðir ódeilanlegt, í þessu samhengi samheiti við samfleytt.

Það eru tvær leiðir til að útfæra lokka:

  1. Stuðningur við vélbúnað fyrir atómaðgerðir - sérstakar samsetningarleiðbeiningar sem eru framkvæmdar í heild, svo sem B. Próf- og set. Verið klár (og ber afleiðingarnar) - reiknirit Peterson.

Í smáatriðum í dæminu þínu er hvort tveggja óvíst. ef ég skil rétt, þá meinarðu eitthvað svona:

almenningsflokkur Óviss {einkaaðili ulock = nýr hlutur (); opinber int Ótryggt1 {fá; stilla; } = 0; einkaaðili _unsafe2 = 0; public int Unsafe2 {get {lock (ulock) {return _unsafe2; }} stilltu {læsa (ulock) {_unsafe2 = gildi; }}}}

Prófkóði:

var u = nýtt Óöruggt (); Samhliða.For (0, 10000000, _ => {u.Unsafe1 ++;}); Samhliða.For (0, 10000000, _ => {u.Unsafe2 ++;}); Console.WriteLine (string.Format ("{0} - {1}", u.Unsafe1, u.Unsafe2));

Niðurstaða (ein af mörgum mögulegum):

4648265 - 4149827

Í báðum tilvikum hvarf meira en helmingur uppfærslanna.

Ástæðan fyrir þessu er sú að ++ er ekki atóm - það eru í raun þrjár aðskildar aðgerðir:

  1. Fáðu gildi. Bættu við 1 við gildi. Stilla gildi.

Við getum lagað þetta með því að bjóða upp á stigvaxandi aðgerð sem er lotukerfið. Það eru margar leiðir til að gera þetta, en hér eru tvær:

almennur flokkur Safe {private object slock = new object (); opinber int Safe1 {fá; stilla; } opinbert ógilt SafeIncrement1 () {læsa (ulock) {this.Safe1 ++; }} persónulegur int _safe2 = 0; public int Safe2 {get {return _safe2; } setja {_safe2 = gildi; }} ógilt SafeIncrement2 () {Interlocked.Increment (ref _safe2); }}

Prófkóði:

var s = nýtt Safe (); Samhliða.For (0, 10000000, _ => {am SafeIncrement1 ();}); Samhliða.For (0, 10000000, _ => {am SafeIncrement2 ();}); Console.WriteLine (string.Format ("{0} - {1}", á Safe1, á Safe2));

Niðurstöðurnar eru réttar í báðum tilvikum. Sú fyrri læsir bara öllu samsettu ++ aðgerðinni, en hið síðara notar vélbúnaðarstuðning við atómaðgerðir.

Athugaðu að annað afbrigðið hér að ofan með Interlocked.Inrrement er miklu hraðara, en hefur í raun lægra stig og býður aðeins upp á takmarkaða virkni. Hins vegar er hægt að nota aðgerðirnar í samtengdum pakka til að hrinda í framkvæmd eftirfarandi:

  1. Þekktir lásar, þekktir sem „svartsýnt samsömun“ vegna þess að þeir gera ráð fyrir að ferlið verði rofið, byrja ekki fyrr en þeir hafa eignast sameiginlega auðlind. Þegar þú berð saman og skiptirðu skaltu nota sérstakt „Kanarí“ gildi sem þú skráir í byrjun og vertu síðan viss um að ekkert hafi breyst undir þér í lokin. Hugmyndin er að annar þráður drepi kanarífuglinn svo þú veist að þú verður að endurtaka viðskipti þín frá byrjun. Þetta gengur út frá því að eigin kóði þinn sé lotukerfið. Þú getur ekki skrifað tímabundna niðurstöðu í samnýttri stöðu. Þú verður annað hvort að ná árangri alveg eða mistakast alveg (eins og þú hafir ekki framkvæmt neinar aðgerðir).

svara 2:

Tveir gjörólíkir hlutir. Thread-safe þýðir aðgerð sem er skrifuð á þann hátt að það er hægt að hringja ítrekað af mörgum mismunandi þræði án þess að hver þráður trufli virkni annars þráðs (t.d. með því að breyta gildi ef einni breytu er breytt af öðrum Þráður er notaður).

Atomic þýðir (ef ég veit hvert þú ert að fara með það) að dæmi um hlut verður til. Óháð því hversu oft það er vísað til, þetta eina tilvik (frá hvaða þráð sem er) birtist alltaf.


svara 3:

Atómaðgerðir eru leið til að ná fram þráðöryggi með því að nota annað hvort gerð af læsingu, svo sem slöngur eða hálfgerðar, sem nota atómaðgerðir innbyrðis, eða með því að innleiða láslausa samstillingu með því að nota lotukerfis- og geymslu girðingar.

Atómaðgerðir á frumstæðum gagnategundum eru því tæki til að ná þráðöryggi, en tryggja ekki sjálfkrafa þráðöryggi þar sem þú framkvæmir venjulega margar aðgerðir sem treysta á hvor aðra. Þú verður að sjá til þess að þessar aðgerðir séu framkvæmdar samfellt, t.d. B. með mutexes.

Já, að skrifa eina af þessum atómgagnategundum í C # er þráður örugg, en það gerir aðgerðina sem þú notar í þráð ekki örugg. Það tryggir aðeins að skrifaðgerðin sé framkvæmd á réttan hátt, jafnvel þó að annar þráður hafi aðgang að henni „á sama tíma“. Engu að síður, næst þegar þú lest frá núverandi þráð, er ekki tryggt að áður skrifað gildi sé haldið, þar sem annar þráður gæti hafa skrifað honum, heldur aðeins að lesgildið sé gilt.