Atomic leest en schrijft over eigenschappen

Deze vraag is al eerder gesteld maar ik begrijp het nog steeds niet volledig, dus hier gaat het.

Als ik een klasse heb met een eigenschap (een niet-nulbare dubbele of int) - kan ik de eigenschap met meerdere threads lezen en schrijven?

Ik heb ergens gelezen dat aangezien doubles 64 bytes zijn, het mogelijk is om een ​​dubbele eigenschap op één thread te lezen terwijl deze op een andere wordt geschreven. Dit zal ertoe leiden dat de leesthread een waarde retourneert die niet de oorspronkelijke waarde noch de nieuwe geschreven waarde is.

Wanneer kan dit gebeuren? Is het ook mogelijk met ints? Is dit mogelijk met zowel 64- als 32-bits toepassingen?

Ik heb deze situatie niet kunnen repliceren in een console

4

2 antwoord

Als ik een klasse met een eigenschap (een niet-nulbaar dubbel of int) heb - kan ik de eigenschap met meerdere threads lezen en schrijven?

Ik neem aan dat je bedoelt "zonder synchronisatie".

double and long are both 64 bits (8 bytes) in size, and are not guaranteed to be written atomically. So if you were moving from a value with byte pattern ABCD EFGH to a value with byte pattern MNOP QRST, you could potentially end up seeing (from a different thread) ABCD QRST or MNOP EFGH.

Met correct uitgelijnde waarden van 32 bits of minder, is de atomiciteit gegarandeerd. (Ik kan me niet herinneren dat er garanties zijn dat de waarden zullen goed zijn uitgelijnd, maar ik geloof dat ze standaard zijn, tenzij je een bepaalde lay-out via attributen forceert.) De C# 4-specificatie noemt zelfs de uitlijning niet in paragraaf 5.5 over atomiciteit:

Lezen en schrijven van de volgende gegevenstypen zijn atomaire: bool, char, byte, sbyte, short, ushort, uint, int, float en reference types. Bovendien zijn het lezen en schrijven van typen enum met een onderliggend type in de vorige lijst ook atomisch. Leest en schrijft over andere typen, inclusief lange, ulong, dubbele en decimale, evenals door de gebruiker gedefinieerde typen, zijn niet gegarandeerd atomair. Afgezien van de bibliotheekfuncties die voor dat doel zijn ontworpen, is er geen garantie voor atomisch lezen, wijzigen of schrijven, zoals in het geval van een toename of afname.

Bovendien is atomiciteit niet hetzelfde als volatiliteit - dus zonder extra zorg te nemen, kan het lezen van één thread een "schrijven" van een andere thread niet "zien".

3
toegevoegd
Maar ik heb begrepen dat dit bc is in 32-bits apps, het programma kan maar de helft van de variabele tegelijk verwerken - dus als ik een 64-bits app zou draaien, zou het verdubbelen dan veilig zijn?
toegevoegd de auteur William, de bron
Voor mijn toepassing denk ik echt niet dat oude leugens een probleem zijn - is er een manier waarop ik deze situatie zou kunnen repliceren zodat ik kan bevestigen of het in 64-bit draaien atomair is?
toegevoegd de auteur William, de bron
@ William: in een 64-bits proces geloof ik dat het atomair zou zijn. Maar je zou nog steeds het probleem hebben van verouderde reads. Tenzij u echt niet geïnteresseerd bent in het weergeven van gegevens die door een andere thread zijn geschreven, zou ik de klasse Vergrendeld of een vergrendeling gebruiken.
toegevoegd de auteur Jon Skeet, de bron
@William: De CLI-specificatie maakt deze garantie: "Een conforme CLI garandeert dat lees- en schrijftoegang tot correct uitgelijnde geheugenlocaties die niet groter zijn dan de oorspronkelijke woordgrootte (de grootte van het type native int) atomair is (zie §12.6.2) wanneer alle schrijftoegangen tot een locatie dezelfde grootte hebben. " - maar ik weet niet welke uitlijning is gegarandeerd. Merk op dat je het gemakkelijk zou kunnen vinden om de niet-atomiciteit toch te repliceren.
toegevoegd de auteur Jon Skeet, de bron

Deze bewerkingen zijn niet atomisch, daarom is de Interlocked bestaat in de eerste plaats, met methoden zoals Increment (Int32) en Increment (Int64) .

Om de veiligheid van threads te garanderen, moet u ten minste deze klasse gebruiken, zo niet complexere vergrendeling (met ReaderWriterLockSlim , bijvoorbeeld voor het geval u de toegang tot groepen met eigenschappen wilt synchroniseren).

1
toegevoegd
Dus ben je het oneens met de Jon (hierboven) en zeg je dat ints niet thread safe zijn?
toegevoegd de auteur William, de bron
Het is niet dat ik het niet eens ben of niet. Jon legde de theoretische aspecten van atomaire lezen/schrijven over ingebouwde gegevenstypen uit. Ik zeg dat je in de praktijk Interlocked of elk ander synchronisatiemechanisme moet gebruiken om de speciale gevallen en uitzonderingen die Jon hieronder beschrijft te vermijden.
toegevoegd de auteur Marcel N., de bron