Adatok szinkronizálása többszálú használatra

Ha több szál is indíthat hívásokat egyetlen objektum tulajdonságaira és metódusára, kritikus fontosságú, hogy ezek a hívások szinkronizálódjanak. Ellenkező esetben az egyik szál megszakíthatja a másik szál működését, és az objektum érvénytelen állapotban maradhat. Az osztályt, amelynek tagjai védettek az ilyen megszakításoktól, szálbiztosnak nevezzük.

.NET számos stratégiát biztosít a példányokhoz és statikus tagokhoz való hozzáférés szinkronizálásához:

  • Szinkronizált kódrégiók. A Monitor osztály vagy az osztályhoz biztosított fordítótámogatás használatával csak a szükséges kódblokkot szinkronizálhatja, ezzel javítva a teljesítményt.

  • Manuális szinkronizálás. A .NET osztálytár által biztosított szinkronizálási objektumokat használhatja. Lásd a szinkronizálási primitívek áttekintését, amely tartalmazza az Monitor osztály megvitatását.

  • Szinkronizált környezetek. Kizárólag a .NET-keretrendszerbeli alkalmazások esetében használhatja a(z) SynchronizationAttribute elemet a ContextBoundObject objektumok egyszerű, automatikus szinkronizálásának engedélyezésére.

  • Gyűjteményosztályok a System.Collections.Concurrent névtérben. Ezek az osztályok beépített szinkronizált hozzáadási és eltávolítási műveleteket biztosítanak. További információ: Thread-Safe Gyűjtemények.

A közös nyelvi futtatókörnyezet olyan szálmodellt biztosít, amelyben az osztályok számos kategóriába sorolhatók, amelyek a követelményektől függően különböző módokon szinkronizálhatók. Az alábbi táblázat azt mutatja be, hogy az adott szinkronizálási kategóriához tartozó mezők és metódusok milyen szinkronizálási támogatást kapnak.

Category Globális mezők Statikus mezők Statikus metódusok Példánymezők Példány metódusai Adott kódblokkok
Nincs szinkronizálás No No No No No No
Szinkronizált környezet No No No Igen Igen No
Szinkronizált kódrégiók No No Csak ha meg van jelölve No Csak ha meg van jelölve Csak ha meg van jelölve
Manuális szinkronizálás Kézikönyv Kézikönyv Kézikönyv Kézikönyv Kézikönyv Kézikönyv

Nincs szinkronizálás

Ez az objektumok alapértelmezett értéke. Bármely szál bármikor hozzáférhet bármilyen metódushoz vagy mezőhöz. Ezeket az objektumokat egyszerre csak egy szál érheti el.

Manuális szinkronizálás

A .NET osztálytár számos osztályt biztosít a szálak szinkronizálásához. Lásd a szinkronizálási primitívek áttekintését.

Szinkronizált kódterületek

Az osztály vagy a fordító kulcsszó használatával szinkronizálhatja a Monitor kódblokkokat, a példánymetodusokat és a statikus metódusokat. A szinkronizált statikus mezők nem támogatottak.

A Visual Basic és a C# is támogatja a kódblokkok megjelölését egy adott nyelvi kulcsszóval, a lock C# utasítással vagy a SyncLock Visual Basic utasítással. Amikor egy szál végrehajtja a kódot, kísérlet történik a zárolás megszerzésére. Ha a zárolást már egy másik szál megszerezte, a szál blokkolódik, amíg a zárolás elérhetővé nem válik. Amikor a szál kilép a szinkronizált kódblokkból, a zárolás felszabadul, függetlenül attól, hogy a szál hogyan lép ki a blokkból.

Note

A 9. és a 13. C# vagy újabb .NET esetén, ha a lock cél egy dedikált System.Threading.Lock példány, az lock utasítás egy szinkronizált régió létrehozásához használjaLock.EnterScope().

A Visual Basic nem támogatja a(z) System.Threading.Lock elemet a(z) SyncLock elemben, ezért továbbra is a(z) SyncLock elemet használja dedikált privát hivatkozástípussal.

Ha a lock cél nem a(z) Lock példánya, akkor az összes SyncLock használat esetén a fordító a(z) Monitor.Enter és Monitor.Exit elemeket használja. A megvalósítás miatt továbbra is használhat más Monitor metódusokat a szinkronizált régióban.

Egy metódust egy MethodImplAttribute attribútummal is elláthat, amelynek az értéke MethodImplOptions.Synchronized; ennek ugyanaz a hatása, mint a Monitor vagy valamelyik fordítói kulcsszó használatának a metódus teljes törzsének zárolására.

Thread.Interrupt használható arra, hogy megszakítson egy blokkoló művelet miatt várakozó szálat, például amikor az egy szinkronizált kódrészlethez való hozzáférésre vár. Thread.Interrupt a szálaknak az olyan műveletekből való kiléptetésére is használható, mint a Thread.Sleep.

Important

Ne tegye zárolttá a típust — azaz C#-ban typeof(MyType), Visual Basicben GetType(MyType), illetve C++-ban MyType::typeid — a static metódusok (Visual Basicben: Shared metódusok) védelme érdekében. Ehelyett használjon privát statikus objektumot. Hasonlóképpen, ne használja a this elemet példánymetódusok zárolására a C#-ban (a Me elemet a Visual Basicben). Használjon inkább privát objektumot. Az osztályokat vagy példányokat nem a saját kóddal lehet zárolni, ami holtpontot vagy teljesítményproblémákat okozhat.

Fordító támogatása

A Visual Basic és a C# is támogat egy olyan kulcsszót, amely a Monitor.Enter és Monitor.Exit használatával zárolja az objektumot. Visual Basic támogatja a SyncLock utasítást; A C# támogatja a zárolási utasítást.

Mindkét esetben, ha a kódblokkban kivétel keletkezik, a lock vagy a SyncLock által megszerzett zár automatikusan felszabadul. A C# és a Visual Basic fordítók egy try/finally blokkot generálnak, a Monitor.Enter hívással a try blokk elején, és a Monitor.Exit hívással a finally blokkban. Ha a lock vagy a SyncLock blokkon belül kivétel keletkezik, a finally kezelő lefut, hogy elvégezhesse a szükséges tisztítási műveleteket.

Szinkronizált környezet

A SynchronizationAttribute használatával bármely ContextBoundObject összes példánymetódusa és mezője szinkronizálható, de ez csak .NET Framework-alapú alkalmazásokban lehetséges. Az ugyanabban a környezetben lévő tartomány összes objektuma ugyanazt a zárolást használja. Több szál is hozzáférhet a metódusokhoz és a mezőkhöz, de egyszerre csak egyetlen szál érhető el.

Lásd még