Jo esikoulussa lapsille opetetaan, kuinka yhteiselo muiden kanssa on välillä hankalaa – varsinkin, kun tapellaan samoista leluista. Samalla kantapään kautta opitaan, että kannattaa olla joko itsekäs tai, vastapuolen koosta riippuen, antaa suosiolla lelu sitä pyytävälle. Lopputuloksena on, että pienimmät ja heikoimmat sortuvat elon tiellä ja jäävät aina ilman leluja, ellei täti tai setä ole auttamassa. Fiksuimmat tosin huomasivat, että yhdessäkin on mahdollista leikkiä samalla lelulla.

Tiedemaailmalla on paha tapa keksiä yksinkertaisille asioille hienolta kuulostavat termit. Siksipä näille jo esikoulussa opituille asioille on omat terminsä: rinnakkaisuus, kriittinen alue, nälkiintyminen, käänteisprioriteettiongelma, poissulkevuus… Näitä hienolta kuulostavia termejä käytetään myös yliopistoissa: rinnakkaisuus on välillä hankalaa ja parempi on antaa vain yhden käsitellä samaa resurssia samanaikaisesti. Toisin sanoen, pistetään semafori kaikkiin mahdollisiin paikkoihin (ja varmuuden vuoksi mahdottomiinkin), jotta resurssia käsittelevä ns. kriittinen alue olisi varmasti suojattu rinnakkaisuuden ongelmilta.

Poissulkeminen semaforeilla on tehokas lääke, mutta sillä on muiden tehokkaiden lääkkeiden tapaan omat sivuvaikutuksensa. Koska semafori käytännössä sarjallistaa lukitun kriittisen alueen suorituksen, hidastuu koko ohjelman suoritus selvästi, jos useampi säie käsittelee samaa resurssia. Lisäksi jotkin säikeet voivat jäädä kokonaan ilman suoritusaikaa. Toki tätä voidaan kiertää sillä, että säikeet eivät käsittelekään samaa resurssia vaan resurssi on jaettu osiksi (esim. MapReduce), joita voidaan käsitellä turvallisesti rinnakkain. Tämä lähestymistapa toki toimii varsin hyvin tilanteissa, jossa käsiteltävä tieto jakautuu luonnollisesti toisistaan riippumattomiksi osiksi.

Poissulkemisvaltaväestön lisäksi on pieni, mutta vaikutusvaltainen ”kerho”, jonka mielestä asiat voidaan hoitaa järkevämminkin kuin antamalla kriittinen alue yksinoikeudella yksittäisen säikeen käyttöön. Tarkoituksena on tehdä ohjelmasta lukkiutumattomia (non-blocking, lock-free tai lockless) niin, ettei edes vihamielinen vuoronnuspäätös voi lukittaa ohjelmaa. Semaforeilla varustetun ”perinteisen” rinnakkaisen ohjelmanhan saa helposti lukkoon pysäyttämällä kriittisen alueen lukinneen säikeen suoritus. Reaaliaikajärjestelmissä lock-free -algoritmit ovat suorastaan ohjelmoijan päivän pelastus. Samalla on mahdollista päästä myös muista rinnakkaisuuden ongelmista eroon.

Lock-free -ohjelmointi hyödyntää lähes kaikista prosessoreista löytyviä atomisia käskyjä, jotka tekevät useamman asian (read-modify-write) näennäisesti samanaikaisesti niin, etteivät muut säikeet tai prosessorit pääse sotkemaan käskyn suoritusta, eivätkä näkemään prosessin välituloksia. Eräs käytetyin tällaisista käskyistä on vuodelta 1970 peräisin oleva compare_and_swap (ja sen sukulaiset test_and_set tai compare_exchange), joka ottaa parametreikseen muistiosoitteen, odotetun ja uuden muistipaikan arvon. Jos muistipaikasta löytyy odotettu arvo, sen paikalle kirjoitetaan uusi arvo. Paluuarvona käskystä on tieto, vaihdettiinko muistipaikan arvoa vai ei.

Vaikka tarvittava laitetuki onkin ollut olemassa jo yli 40 vuotta, on lock-free -tutkimus ollut kohtuullisen pienen piirin harrastus aina viime vuosikymmeniin asti. Toisaalta Michael ja Scott ovat julkaisseet aihepiiriä sivuten vuonna 1996 varsin mielenkiintoisen artikkelin. Tilanne muuttui muutama vuosi sitten, kun uuden C++11 -standardin myötä tarvittavat työkalut on tuotu rivikoodarin nenän eteen. Lopputuloksena jokainen itseään kunnioittava nörtti tekee nyt oman lock-free -jonototeutuksensa heti Hello World!in jälkeen. Toki ABA-ongelman ratkaiseminen saattaa unohtua kaikessa kiireessä, kuten monessa julkisuudessa levitetyssä esimerkissäkin on ikävä kyllä tapahtunut.

Jos asia kiinnostaa enemmän, on hyvä lähtökohta tutustumiselle esimerkiksi Preshing on Programming blogi. Laiskemmille löytyy Sutterin aiheesta pitämä ansiokas esitys videomuodossa. On toki muistettava, että muiden hienojen asioiden tapaan lock-free -ohjelmointi ei kuitenkaan ole hopealuoti, joka ratkaisee kaikki maailman ongelmat. Pahimmillaan monimutkaisten algoritmien huono toteutus voi jopa heikentää tai hidastaa ohjelman toimintaa. Onneksi useat ohjelmointikielten kirjastot sisältävät jo valmiit toteutukset lock-free -tietorakenteille. Silti, kannattaa tutkia tarkkaan, mistä ohjelman ongelmat oikeasti johtuvat ja ratkaisisiko lock-free -ohjelmointi ne.