Spinlock tai spinlock ( englanniksi spinlock - cyclic lock ) on matalan tason synkronointiprimitiivi [1] , jota käytetään moniprosessorijärjestelmissä kriittisten koodiosien suorittamisen vastavuoroiseen poissulkemiseen aktiivisen odotussilmukan avulla [ 2] . Sitä käytetään tapauksissa, joissa lukon odotusajan odotetaan olevan lyhyt [2] tai jos suorituskonteksti ei salli siirtymistä estettyyn tilaan [3] .
Spinlockit ovat samanlaisia kuin mutexit , joten voit käyttää vähemmän aikaa säikeen estämiseen, koska sinun ei tarvitse siirtää säiettä estettyyn tilaan. Mutexien tapauksessa saattaa olla tarpeen kutsua ajastinta säikeen tilan muuttamiseksi ja lisäämään se lukituksen avaamista odottavien säikeiden luetteloon. Spinlockit eivät käytä ajastinta ja käyttävät odotussilmukkaa muuttamatta säikeen tilaa, mikä tuhlaa CPU-aikaa odottamaan, että toinen säie vapauttaa lukituksen. Tyypillinen spinlockin toteutus on yksinkertainen syklinen spinlock-muuttujan saatavuuden tarkistus [1] .
Fyysisesti spinlock on muistissa oleva muuttuja ja se toteutetaan atomioperaatioilla , joiden on oltava läsnä prosessorin käskyjoukossa . Jokainen prosessori, joka haluaa käyttää jaettua resurssia, kirjoittaa ehdollisen arvon " busy " tähän muuttujaan käyttämällä swap-operaation analogia (x86-arkkitehtuurissa - xchg). Jos muuttujan edellinen (komennolla palautettu) arvo oli " free ", tietyn prosessorin katsotaan käyttäneen resurssia, muuten prosessori palaa swap-toimintoon ja kiertää spinlockin läpi, kunnes se vapautuu. Työskenneltyään jaetun resurssin kanssa prosessorin - spinlockin omistajan - on kirjoitettava siihen ehdollinen arvo " free ".
Esimerkki spinlockin toteutuksesta x86-asentajassa:
mov eax , spinlock_address mov ebx , SPINLOCK_BUSY odotusjakso: xchg [ eax ], ebx ; xchg on ainoa ohje, joka on atominen ilman etuliitettä lock cmp ebx , SPINLOCK_FREE jnz wait_cycle ; <kriittinen osio on kaapattu tähän säiettä, työ jaetun resurssin kanssa on käynnissä täällä> mov eax , spinlock_address mov ebx , SPINLOCK_FREE xchg [ eax ], ebx ; käytä xchg:tä atomin muutokseen ; 3 viimeistä ohjetta tulee korvata mov [spinlock_address], SPINLOCK_FREE - ; tämä lisää nopeutta tarpeettoman väylän eston puuttumisen vuoksi ja mov suoritetaan joka tapauksessa atomisesti ; (mutta vain jos spinlock_address on kohdistettu sanan rajaan)Älykkäämpi toteutus käyttäisi tavanomaista toimintoa atomioperaation sijaan silmukassa tapahtuvaan kyselyyn ja atomioperaatiota vain sieppausyrityksiin. Tosiasia on, että atomimuistitoimintojen toteutus tapahtuu siten, että laitteisto estää prosessorin järjestelmäväylän atomitoiminnan ajaksi (johon sisältyy lukeminen, muokkaaminen ja kirjoittaminen). Näiden kolmen toiminnon aikana väylällä ei voida suorittaa muita toimintoja, mikä heikentää järjestelmän muiden prosessorien suorituskykyä (jos niillä on yhteinen väylä ), vaikka niillä ei olisi mitään tekemistä tämän spinlockin kanssa.
Käytössä ovat myös ns. jonossa olevat spinlockit - "jonossa olevat spinlockit". Sen sijaan, että atomimuuttujalle määritettäisiin 0 tai 1, ne käyttävät rakenteen atomilisäystä luettelon päähän, kun taas luettelon otsikko on "osoitin"-tyyppinen atomimuuttuja.
Jonossa olevien spinlockien hyödylliset ominaisuudet:
Spinlockeja käytetään pienten koodin osien synkronoimiseen, kun monimutkaisempien mekanismien käyttö on kohtuutonta tai mahdotonta. Synkronointiprimitiivien ja säikeenhallinnan toteutus vaatii välttämättä lukkoja, jotka suojaavat suoritettavaksi valmiita säikeitä ja objekteissa odottavien säikeiden luetteloita. Tällainen lukko voi olla vain spinlock sen erittäin alhaisen tason vuoksi. Siten spinlock on alin synkronointiprimitiivi, johon kaikkien muiden toteutus perustuu.
Windows-versiot Windows 7:stä mukaan lukien käyttävät lukitsemattomien tietorakenteiden paradigmaa toteuttaakseen lähettäjän/aikataulun. Näin ollen ne säästyivät ainoalta globaalilta spinlockilta KiDispatcherLockilta, joka on yksi raskaimmin ladatuista käyttöjärjestelmän ytimissä.
On laajalle levinnyt mielipide, että monitehtäväkäyttöjärjestelmässä toimivissa käyttäjäsovelluksissa spinlockien käyttöä ei voida hyväksyä, koska spinlockin vapautumisen odottaminen johtaa aktiiviseen odottamiseen silmukassa, joka tuhlaa CPU:n laskentaresursseja, ja korkean tason primitiivit on käytetään synkronoimaan käyttäjäohjelmia, mikä merkitsee passiivista odottamista - jos tietty säiettä ei voi jatkaa suoritusta, se antaa ohjauksen käyttöjärjestelmälle, eikä pyöri spinlock-odotussilmukassa (joka voi olla loputon). Itse asiassa tämä väite on 100 % totta vain yksiprosessorijärjestelmille. Monissa tapauksissa spinlockien käyttäminen SMP -konfiguraatioissa johtaa tehokkuushyötyihin, jos kysely ja spinlockin hankkiminen on nopeampaa kuin mutex-hankinnan kutsuminen ytimessä.
Pääkriteeri tässä on kiista - resurssista käytävän kilpailun "jäykkyys". Kevyesti ladattu resurssi, joka ei ole suosittu suoritussivusto, käyttäytyy eri tavalla kuin raskaasti ladattu resurssi, jota kaapataan ja vapautetaan hyvin usein.
Lisäksi samassa Windowsissa on erilaisia mutexeja (esimerkiksi hyvin tunnettu CRITICAL_SECTION/EnterCriticalSection/LeaveCriticalSection tai sen synonyymi käyttöjärjestelmän ytimessä - FAST_MUTEX/ExAcquireFastMutex/ExReleaseFastMutex), jotka toimivat ensin spininä. arvokyselyn muistiin, ja vasta sitten, useiden kyselyjen jälkeen, siirry ytimeen esto-odotukseen. Tällaisissa kohteissa yhdistyvät spinlockien (sieppauksen vähimmäiskustannukset) ja mutexien (ei suorittimen resurssien hukkaa kyselyyn) parhaat ominaisuudet.
Tapauksia, joissa spinlockien käyttö käyttäjätilassa antaa konkreettisen vaikutuksen:
Kuitenkin "nopeiden mutexien", kuten Win32:n CRITICAL_SECTION, käyttö tekee kaikesta yllä mainitusta tarpeettomaksi käyttäjätilassa.
Tapaukset, joissa spinlockien käyttö ei ole perusteltua ja se on prosessoriresurssien tuhlausta:
Nykyaikaisissa prosessoreissa lepotila voi olla erittäin nopea liukuhihna-arkkitehtuurin erityispiirteistä johtuen, mikä voi käämittävien tyhjäkäyntijaksojen lisäksi johtaa voimakkaampaan lämpenemiseen kuin normaalikäytössä.
Pentium 4 :ssä ja uudemmissa Intel - suorittimien malleissa otettiin käyttöön erityinen kokoonpanokäsky lisätä taukosilmukan sisään ( opcode 0xf3 0x90, samanlainen kuin rep nop, jotta se on yhteensopiva vanhempien prosessorien kanssa), jonka tarkoituksena on ohjeistaa prosessori, että tämä sykli on odotussilmukka, ja sallii prosessorin tukea useita säikeitä samassa ytimessä siirtyä seuraavaan säikeeseen.
Windows 7:n jälkeiset Windows-versiot on optimoitu toimimaan "vieraana" virtuaalikoneessa, ja sen sijaan, että keskeytettäisiin tapauksissa, joissa käyttöjärjestelmä toimii vieraana, erityinen kutsu "ilmoittaa hypervisorille, että olemme odotussilmukassa" käytetään.
Spinlockia automaattisella kasvulla, kunnes täysi mutex kaapataan tietyn kierrosluvun umpeutumisen jälkeen, käytetään esimerkiksi Windowsin kriittisissä osissa optimointia varten, mikä tarkoittaa, että mutexille ei anneta kutsuja kilpailun puuttuessa. resurssia varten.