Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Als u gelijktijdigheidsfouten in uw multithreaded-programma wilt voorkomen, volgt u altijd een geschikte vergrendelingsdiscipline en gebruikt u SAL-aantekeningen.
Gelijktijdigheidsfouten zijn bekend moeilijk te reproduceren, te diagnosticeren en op te lossen omdat ze niet-deterministisch zijn. Redenering over thread-interleaving is in het beste stadium moeilijk en wordt onpraktisch wanneer u een hoofdtekst met code ontwerpt die meer dan een paar threads bevat. Daarom is het raadzaam om een vergrendelingsdiscipline in uw multithreaded programma's te volgen. Als u bijvoorbeeld een vergrendelingsvolgorde volgt tijdens het verkrijgen van meerdere vergrendelingen, helpt u impasses te vermijden, en het verkrijgen van de juiste beveiligingsvergrendeling voordat u toegang krijgt tot een gedeelde resource helpt racecondities te voorkomen.
Helaas kunnen schijnbaar eenvoudige vergrendelingsregels verrassend moeilijk te volgen zijn in de praktijk. Een fundamentele beperking in de programmeertalen en compilers van vandaag is dat ze niet rechtstreeks ondersteuning bieden voor de specificatie en analyse van gelijktijdigheidsvereisten. Programmeurs moeten vertrouwen op informele codeopmerkingen om hun intenties uit te drukken over hoe ze vergrendelingen gebruiken.
Gelijktijdigheid SAL-aantekeningen zijn ontworpen om u te helpen bij het instellen van bijbehorende neveneffecten van vergrendeling, verantwoordelijkheid voor het vergrendelen, gegevensbeheer, de hiërarchie van vergrendelvolgorde en ander verwacht vergrendelingsgedrag. Door impliciete regels expliciet te maken, bieden SAL-gelijktijdigheidsaantekeningen een consistente manier om vast te leggen hoe uw code gebruikmaakt van vergrendelingsregels. Gelijktijdigheidsaantekeningen verbeteren ook de mogelijkheid van hulpprogramma's voor codeanalyse om racevoorwaarden, impasses, niet-overeenkomende synchronisatiebewerkingen en andere subtiele gelijktijdigheidsfouten te vinden.
Algemene richtlijnen
Door annotaties te gebruiken, kunt u de contracten die worden geïmpliceerd door functie-definities tussen implementaties (callees) en aanroepers (callers) aangeven. U kunt ook invarianten en andere eigenschappen van het programma uitdrukken die de analyse verder kunnen verbeteren.
SAL ondersteunt veel verschillende soorten vergrendelingsprimitieven, bijvoorbeeld kritieke secties, mutexes, spinvergrendelingen en andere resourceobjecten. Veel concurrentieannotaties nemen een vergrendelingsexpressie als parameter. Standaard wordt een vergrendeling aangeduid met de padexpressie van het onderliggende vergrendelingsobject.
Enkele regels voor het eigendom van threads om rekening mee te houden:
Spin locks zijn ontelbare vergrendelingen waarvan het eigenaarschap van de thread duidelijk is.
Mutexes en kritieke secties zijn vergrendelingen met telling die duidelijke thread-eigendom hebben.
Semaforen en signalen zijn getelde vergrendelingen die geen duidelijke eigendom van threads hebben.
Aantekeningen vergrendelen
De volgende tabel bevat de vergrendelingsaantekeningen.
| Aantekening | Beschrijving |
|---|---|
_Acquires_exclusive_lock_(expr) |
Annoteert een functie en geeft aan dat de functie na afloop het exclusieve aantal vergrendelingen van het vergrendelingsobject dat benoemd is door expr met één verhoogt. |
_Acquires_lock_(expr) |
Annotaties maken bij een functie en aangeven dat in de toestand na het uitvoeren van de functie het aantal vergrendelingen van het vergrendelingsobject dat expr genoemd wordt, met één wordt verhoogd. |
_Acquires_nonreentrant_lock_(expr) |
De vergrendeling waarmee de naam is opgegeven expr , wordt verkregen. Er wordt een fout gerapporteerd als de vergrendeling al is vastgehouden. |
_Acquires_shared_lock_(expr) |
Annotaties maken bij een functie en aangeven dat de functie na afloop de teller van gedeelde sloten van het vergrendelingsobject met de naam expr met één verhoogt. |
_Create_lock_level_(name) |
Een instructie die het symbool name aangeeft als een vergrendelingsniveau, zodat het kan worden gebruikt in de aantekeningen _Has_Lock_level_ en _Lock_level_order_. |
_Has_lock_kind_(kind) |
Aantekeningen toevoegen aan een object om de typegegevens van een resourceobject te verfijnen. Soms wordt een gemeenschappelijk type gebruikt voor verschillende soorten resources en is het overbelaste type niet voldoende om de semantische vereisten tussen verschillende resources te onderscheiden. Hier volgt een lijst met vooraf gedefinieerde kind parameters:_Lock_kind_mutex_Soort id vergrendelen voor mutexes. _Lock_kind_event_ID-type voor vergrendeling bij evenementen. _Lock_kind_semaphore_Vergrendelings-ID voor semaforen. _Lock_kind_spin_lock_Soort id vergrendelen voor spinvergrendelingen. _Lock_kind_critical_section_Vergrendelingstype-ID voor kritieke secties. |
_Has_lock_level_(name) |
Maakt aantekeningen bij een vergrendelingsobject en kent het het vergrendelingsniveau van name toe. |
_Lock_level_order_(name1, name2) |
Een verklaring die de volgorde van vergrendeling tussen name1 en name2 aangeeft. Vergrendelingen die een niveau name1 hebben, moeten worden verkregen voordat vergrendelingen die een niveau name2 hebben. |
_Post_same_lock_(dst, src) |
Annoteert een functie en geeft aan dat in de poststatus de twee vergrendelingen, dst en src, worden behandeld alsof ze hetzelfde vergrendelingsobject zijn, door de vergrendelingseigenschappen van src toe te passen op dst. |
_Releases_exclusive_lock_(expr) |
Hiermee worden aantekeningen gegeven voor een functie en wordt aangegeven dat de functie in de poststatus het exclusieve vergrendelingsaantal van het vergrendelingsobject met de naam expr met één verlaagt. |
_Releases_lock_(expr) |
Aantekent een functie en geeft aan dat de functie in de post-status het aantal vergrendelingen van het vergrendelingsobject met de naam expr met één vermindert. |
_Releases_nonreentrant_lock_(expr) |
De vergrendeling met de naam expr wordt vrijgegeven. Er wordt een fout gerapporteerd als de vergrendeling momenteel niet wordt vastgehouden. |
_Releases_shared_lock_(expr) |
Annoteert een functie en geeft aan dat in de post-toestand de functie het gedeelde vergrendelingsaantal met één vermindert van het vergrendelingsobject dat wordt genoemd door expr. |
_Requires_lock_held_(expr) |
De functie aantekent en geeft aan dat in de voorafgaande staat het vergrendelingsaantal van het object dat is genoemd door expr ten minste één is. |
_Requires_lock_not_held_(expr) |
Hiermee wordt een functie geannoteerd en wordt aangegeven dat in de voorafgaande staat het aantal vergrendelingen van het object met de naam expr nul is. |
_Requires_no_locks_held_ |
Annoteren van een functie en geeft aan dat het aantal van alle vergrendelingen die bekend zijn bij de controleur nul is. |
_Requires_shared_lock_held_(expr) |
Hiermee wordt een functie genoteerd en wordt aangegeven dat in de pre-staat het aantal gedeelde vergrendelingen van het object met de naam expr ten minste één is. |
_Requires_exclusive_lock_held_(expr) |
Annotateert een functie en geeft aan dat in de pre-staat de exclusieve vergrendelingsaantal van het object dat wordt genoemd door expr ten minste één is. |
SAL-intrinsieken voor niet-blootgestelde vergrendelingsobjecten
Bepaalde vergrendelingsobjecten worden niet weergegeven door de implementatie van de bijbehorende vergrendelingsfuncties. De volgende tabel bevat intrinsieke SAL-variabelen die annotaties mogelijk maken voor functies die op die onzichtbare vergrendelingsobjecten werken.
| Aantekening | Beschrijving |
|---|---|
_Global_cancel_spin_lock_ |
Beschrijft de spinlock-annulering. |
_Global_critical_region_ |
Beschrijft de kritieke regio. |
_Global_interlock_ |
Beschrijft onderling vergrendelde bewerkingen. |
_Global_priority_region_ |
Beschrijft de prioriteitsregio. |
Aantekeningen bij Gedeelde gegevenstoegang
De volgende tabel bevat de aantekeningen voor gedeelde gegevenstoegang.
| Aantekening | Beschrijving |
|---|---|
_Guarded_by_(expr) |
Aantekeningen maken bij een variabele en geeft aan dat wanneer de variabele wordt geopend, het aantal vergrendelingen van het vergrendelingsobject met de naam expr ten minste één is. |
_Interlocked_ |
Aantekeningen toevoegen aan een variabele en is gelijk aan _Guarded_by_(_Global_interlock_). |
_Interlocked_operand_ |
De geannoteerde functieparameter is de doeloperand van een van de verschillende interlocked functies. Deze operanden moeten andere specifieke eigenschappen hebben. |
_Write_guarded_by_(expr) |
Aantekeningen toevoegen aan een variabele en geeft aan dat wanneer de variabele wordt gewijzigd, het aantal vergrendelingen van het vergrendelingsobject met de naam expr ten minste één is. |
Smart Lock en RAII-aantekeningen
Slimme vergrendelingen verpakken doorgaans systeemgeïntegreerde sloten en beheren hun gebruiksduur. De volgende tabel bevat aantekeningen die kunnen worden gebruikt met smart locks en Resource Acquisition Is Initialization (RAII) coderingspatronen met ondersteuning voor move semantiek.
| Aantekening | Beschrijving |
|---|---|
_Analysis_assume_smart_lock_acquired_(lock) |
Geeft aan dat de analyse ervan uitgaat dat er een smart lock is verkregen. Deze aantekening verwacht een verwijzingsvergrendelingstype als parameter. |
_Analysis_assume_smart_lock_released_(lock) |
Geeft aan dat de analyse ervan uitgaat dat er een slimme vergrendeling is vrijgegeven. Deze aantekening verwacht een verwijzingsvergrendelingstype als parameter. |
_Moves_lock_(target, source) |
Beschrijft een move constructor bewerking, waarmee de vergrendelingsstatus van het source object naar het targetobject wordt overgedragen. Het target wordt beschouwd als een nieuw samengesteld object, dus elke status die het eerder had, is verloren en vervangen door de source status. De source status wordt ook opnieuw ingesteld op een schone status zonder aantal vergrendelingen of aliasingsdoel, maar aliassen die ernaar verwijzen, blijven ongewijzigd. |
_Replaces_lock_(target, source) |
Beschrijft move assignment operator semantiek waarbij de doelvergrendeling wordt vrijgegeven voordat de status van de bron wordt overgebracht. U kunt het beschouwen als een combinatie van _Moves_lock_(target, source) voorafgegaan door een _Releases_lock_(target). |
_Swaps_locks_(left, right) |
Beschrijft het standaardgedrag swap , dat ervan uitgaat dat objecten left en right hun status uitwisselen. De uitgewisselde status omvat het aantal vergrendelingen en het aliasdoel, indien aanwezig. Aliassen die verwijzen naar de left en right objecten blijven ongewijzigd. |
_Detaches_lock_(detached, lock) |
Beschrijft een scenario waarin een type lock wrapper dissociatie met de ingesloten resource toestaat. Het is vergelijkbaar met de werking std::unique_ptr van de interne aanwijzer: programmeurs kunnen de aanwijzer extraheren en de slimme aanwijzercontainer in een schone staat laten staan. Vergelijkbare logica wordt ondersteund door std::unique_lock en kan worden geïmplementeerd in aangepaste vergrendelingswikkelaars. De losgekoppelde vergrendeling behoudt de status (aantal vergrendelingen en aliasingsdoel, indien aanwezig), terwijl de wrapper opnieuw wordt ingesteld op nul aantal vergrendelingen en geen aliasdoel, terwijl de eigen aliassen behouden blijven. Er is geen bewerking voor het aantal vergrendelingen (vrijgeven en verkrijgen). Deze aantekening gedraagt zich precies zoals _Moves_lock_, behalve dat het losgekoppelde argument return moet zijn in plaats van this. |
Zie ook
- SAL-aantekeningen gebruiken om C/C++ codefouten te verminderen
- Informatie over SAL
- Aantekeningen toevoegen aan functieparameters en retourwaarden
- Aantekeningen toevoegen aan functiegedrag
- Aantekeningen toevoegen aan Structs en klassen
- opgeven wanneer en waar een aantekening van toepassing is
- Intrinsieke functies
- Aanbevolen procedures en voorbeelden