Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az egyidejűségi hibák elkerülése érdekében a többszálú programban mindig kövesse a megfelelő zárolási szemléletet, és használjon SAL-széljegyzeteket.
Az egyidejűségi hibákat hírhedten nehéz reprodukálni, diagnosztizálni és hibakeresésre felhasználni, mert nemdeterminisztikusak. A szálak egymásba fonódásának értelmezése legjobb esetben is nehéz, és gyakorlatiatlanná válik, amikor több szálat tartalmazó kódtörzset tervez. Ezért érdemes egy zárolási szemléletet követni a többszálú programokban. Ha például több zár megszerzésekor betartja a zárolási sorrendet, elkerülheti a holtpontokat, és a megosztott erőforrások elérése előtt a megfelelő védőzár megszerzése segít megelőzni a versenyhelyzeteket.
Sajnos a látszólag egyszerű zárolási szabályok meglepően nehézkesek lehetnek a gyakorlatban. A mai programozási nyelvek és fordítók alapvető korlátozása, hogy közvetlenül nem támogatják az egyidejűségi követelmények specifikációját és elemzését. A programozóknak informális kódbejegyzésekre kell támaszkodniuk, hogy kifejezzék szándékukat a zárolások használatáról.
Az egyidejűségi SAL-megjegyzések célja, hogy segítsenek meghatározni a zárolási mellékhatásokat, a zárolási felelősséget, az adatőrzést, a zárolási sorrend hierarchiáját és egyéb várható zárolási viselkedést. Az implicit szabályok explicitvá tételével az SAL egyidejűségi széljegyzetei egységes módon dokumentálják, hogyan használja a kód a zárolási szabályokat. Az egyidejűségi széljegyzetek emellett növelik a kódelemzési eszközök azon képességét, hogy versenyfeltételeket, holtpontokat, nem egyező szinkronizálási műveleteket és egyéb finom egyidejűségi hibákat találjanak.
Általános irányelvek
Széljegyzetek használatával megadhatja az implementációk (callees) és az ügyfelek (hívók) közötti függvénydefiníciók által sugallt szerződéseket. A program invariánsait és egyéb tulajdonságait is kifejezheti, amelyek tovább javíthatják az elemzést.
Az SAL számos különböző típusú zárolási primitívet támogat, például kritikus szakaszokat, mutexe-ket, spinzárakat és egyéb erőforrás-objektumokat. Számos egyidejűségi annotáció paraméterként egy zárolási kifejezést vesz igénybe. Konvenció szerint a zárolást az alapul szolgáló zárolási objektum elérési útjának kifejezése jelöli.
Néhány szál tulajdonlására vonatkozó szabály, amit szem előtt kell tartani:
A spinlockok olyan nem számlált zárolások, amelyeknek egyértelmű szál-hozzárendelésük van.
A mutexek és a kritikus szakaszok olyan zárolások, amelyek egyértelmű száltulajdonságokkal rendelkeznek.
A szemaforok és események olyan számláló zárolások, amelyek nem rendelkeznek egyértelmű szálbirtoklással.
Megjegyzések zárolása
Az alábbi táblázat a zárolási széljegyzeteket sorolja fel.
| Jegyzetelés | Leírás |
|---|---|
_Acquires_exclusive_lock_(expr) |
Megjegyzést ad egy függvényhez, és jelzi, hogy post állapotban a függvény egy egységgel növeli az általa elnevezett expr zárolási objektum kizárólagos zárolási számát. |
_Acquires_lock_(expr) |
Megjegyzést fűz egy függvényhez, és jelzi, hogy a függvény a post állapotban eggyel növeli a expr-ként elnevezett zárolási objektum zárolási számlálóját. |
_Acquires_nonreentrant_lock_(expr) |
A(z) expr által elnevezett zár sikeresen szerzett. Hiba jelenik meg, ha a zárolás már meg van tartva. |
_Acquires_shared_lock_(expr) |
Annotál egy függvényt, és jelzi, hogy a függvény a expr által megnevezett zárolási objektum megosztott zárolási számát egyel növeli a post állapotban. |
_Create_lock_level_(name) |
Egy utasítás, amely zárolási szintként definiálja a szimbólumot name, hogy használható legyen a megjegyzésekben _Has_Lock_level_ és _Lock_level_order_. |
_Has_lock_kind_(kind) |
Az erőforrás-objektum típusadatainak finomításához jegyzetekkel adhatja meg az objektumokat. Néha gyakori típust használnak különböző típusú erőforrásokhoz, és a túlterhelt típus nem elegendő a szemantikai követelmények különböző erőforrások közötti megkülönböztetéséhez. Íme az előre definiált kind paraméterek listája:_Lock_kind_mutex_A mutexek zárolási típusának azonosítója. _Lock_kind_event_Az események típusazonosítójának zárolása. _Lock_kind_semaphore_A szemaforok zár típusazonosítója. _Lock_kind_spin_lock_Pörgetőzárak típusazonosítója. _Lock_kind_critical_section_Zárolja a kritikus szakaszok típusazonosítóját. |
_Has_lock_level_(name) |
Annotációt ad a zárolási objektumnak, és megadja a zárolási szintet name. |
_Lock_level_order_(name1, name2) |
Egy kijelentés, amely megadja a zárolási sorrendet az name1 és name2 között. A name1 szinttel rendelkező zárolásokat a name2 szinttel rendelkező zárolások előtt kell megszerezni. |
_Post_same_lock_(dst, src) |
Egy függvényhez megjegyzést fűz, és azt jelzi, hogy utólagos állapotban a két zárolás, dst és src, úgy kezelendő, mintha ugyanaz a zárolási objektum lennének, mivel a zárolási tulajdonságokat a src zárolásról a dst zárolásra alkalmazza. |
_Releases_exclusive_lock_(expr) |
Megjegyzést ad egy függvényhez, és azt jelzi, hogy post állapotban a függvény csökkenti egyel a expr által megnevezett zárolási objektum kizárólagos zárolási számát. |
_Releases_lock_(expr) |
Megjegyzést fűz egy függvényhez, és azt jelzi, hogy utóállapotban a függvény az expr által elnevezett zárolási objektum zárolási számlálóját eggyel csökkenti. |
_Releases_nonreentrant_lock_(expr) |
A(z) expr által megnevezett zárolás fel van oldva. Hiba jelenik meg, ha a zárolás nincs fogva tartva. |
_Releases_shared_lock_(expr) |
Megjegyzést fűz egy függvényhez, és jelzi, hogy a függvény végrehajtása után eggyel csökkenti a zárolási objektum megosztott zárolási számlálóját, amelyet expr nevez meg. |
_Requires_lock_held_(expr) |
Annotál egy függvényt, és jelzi, hogy a expr nevű objektum zárolási száma kezdeti állapotban legalább egy. |
_Requires_lock_not_held_(expr) |
Megjegyzést fűz egy függvényhez, és azt jelzi, hogy az előzetes állapotban a névvel expr ellátott objektum zárolási száma nulla. |
_Requires_no_locks_held_ |
Megjegyzést fűz egy függvényhez, és azt jelzi, hogy az ellenőrző által ismert összes zárolás zárolási száma nulla. |
_Requires_shared_lock_held_(expr) |
Jelzi egy függvényt, és azt is mutatja, hogy a kezdeti állapotban a expr névvel rendelkező objektum megosztott zárolási száma legalább egy. |
_Requires_exclusive_lock_held_(expr) |
Annotál egy függvényt, és jelzi, hogy kezdő állapotban a expr által jelölt objektum kizárólagos zárolási száma legalább egy. |
SAL beépített műveletek rejtett zároló objektumokhoz
Bizonyos zárolási objektumok nem jelennek meg a társított zárolási függvények implementálásával. Az alábbi táblázat azokat a belső SAL-változókat sorolja fel, amelyek lehetővé teszik a magyarázatokat azokon a függvényeken, amelyek ezeken a nem feloldott zárolási objektumokon működnek.
| Jegyzetelés | Leírás |
|---|---|
_Global_cancel_spin_lock_ |
A törlési pörgetőzárat ismerteti. |
_Global_critical_region_ |
A kritikus régiót ismerteti. |
_Global_interlock_ |
Az összekapcsolt műveleteket ismerteti. |
_Global_priority_region_ |
A prioritási régiót ismerteti. |
Megosztott adathozzáférési széljegyzetek
Az alábbi táblázat a megosztott adathozzáférés megjegyzéseit sorolja fel.
| Jegyzetelés | Leírás |
|---|---|
_Guarded_by_(expr) |
Megjegyzést fűz egy változóhoz, és azt jelzi, hogy amikor a változót elérik, az expr-ként megnevezett zárolási objektum zárszáma legalább egy. |
_Interlocked_ |
Egy változó annotálása és egyenértékű a következővel: _Guarded_by_(_Global_interlock_). |
_Interlocked_operand_ |
A jegyzetekkel ellátott függvényparaméter a különböző összekapcsolt függvények egyikének céloperandusa. Ezeknek az operandusoknak egyéb konkrét tulajdonságokkal kell rendelkezniük. |
_Write_guarded_by_(expr) |
Megjegyzést fűz egy változóhoz, és azt jelzi, hogy a változó módosításakor az elnevezett expr zárolási objektum zárolási száma legalább egy. |
Smart Lock és RAII annotációk
Az intelligens zárak általában natív zárakat csomagolnak, és kezelik az élettartamukat. Az alábbi táblázat az intelligens zárolásokkal és az erőforrás-beszerzés is inicializálási (RAII) kódolási mintákkal használható széljegyzeteket sorolja fel, amelyek támogatják a move szemantikát.
| Jegyzetelés | Leírás |
|---|---|
_Analysis_assume_smart_lock_acquired_(lock) |
Arra utasítja az elemzőt, hogy feltételezze, hogy intelligens zárolást szereztek be. Ez a megjegyzés egy referenciazárolási típust vár paraméterként. |
_Analysis_assume_smart_lock_released_(lock) |
Arra utasítja az elemzőt, hogy tételezze fel, hogy egy intelligens zár szabadult fel. Ez a megjegyzés egy referenciazárolási típust vár paraméterként. |
_Moves_lock_(target, source) |
move constructor Egy olyan műveletet ismertet, amely a zárolási állapotot továbbítja az source objektumból a target. A target rendszer újonnan létrehozott objektumnak tekinti, így az előtte lévő állapot elveszik, és az source állapot váltja fel. A source tiszta állapotba lesz visszaállítva zárolási számok vagy alias cél nélkül, de a rá mutató aliasok változatlanok maradnak. |
_Replaces_lock_(target, source) |
Ismerteti a move assignment operator szemantikát, amelyben a célzár fel van szabadítva, mielőtt az állapotot a forrásból átvinnék. Úgy tekintheti, mint a _Moves_lock_(target, source) által megelőzött _Releases_lock_(target) kombinációját. |
_Swaps_locks_(left, right) |
A szokásos swap viselkedést ismerteti, amely feltételezi, hogy az objektumok left és right cserélik az állapotukat. A kicserélt állapot tartalmazza a zárolások számát és az aliasolási célokat, ha vannak ilyenek. Az left aliasok és a right objektumok, amelyekre mutatnak, változatlanok maradnak. |
_Detaches_lock_(detached, lock) |
Egy olyan forgatókönyvet ismertet, amelyben a zárolásburkoló típusa lehetővé teszi a benne foglalt erőforrástól való elválasztást. Hasonlóan működik, mint a std::unique_ptr a belső mutatójával: lehetővé teszi a programozók számára, hogy kinyerjék a mutatót, és tiszta állapotban hagyják az intelligens mutatótárolót. A hasonló logikát std::unique_lock az egyéni zárolásburkolók támogatják, és implementálhatók. A leválasztott zárolás megőrzi az állapotát (a zárolások száma és az aliasolási cél, ha van ilyen), míg a burkoló nullára állítja vissza a zárolások számát és az aliasolási célokat, miközben megtartja a saját aliasait. Nincs művelet a zárolások számán (feloldása és megszerzése). Ez a széljegyzet pontosan úgy viselkedik, mint _Moves_lock_, azzal a különbséggel, hogy a leválasztott argumentumnak return-nek kell lennie, nem pedig this-nek. |
Lásd még
- C/C++ kódhibák csökkentése SAL-széljegyzetek használatával
- A SAL ismertetése
- Függvényparaméterek és visszatérési értékek megjegyzése
- A függvény viselkedésének megjegyzésekkel való ellátása
- Szerkezetek és osztályok jegyzetelése
- Meghatározhatja, hogy mikor és hol alkalmazandó egy megjegyzés
- Belső függvények
- Ajánlott eljárások és példák