Hei, I heite Eirik Torske, og jobba på BBS. I våres så kom i over et interessant lite open-source prosjekt. Det er Deuce – en Java-implementasjon av (såkalt) Software Transactional Memory.
Software Transtactional Memory – heretter bare kalt S.T.M. – e en mekanisme for samtidig adgang til delte ressurser – altså, samtidighetskontroll . Og som vi alle veit: Samtidighetskontroll blir stadig viktigere i vår multi-core hverdag! STM handle om: utfør en definert kodeblokk – på et definert tidspunkt, se om det har gått bra – hvis ikke, rull tilbake alle endringer utført i kodeblokken, og prøv igjen. Detta e også kalt optimistisk låsing – og e analogt med det vi kjenna fra relasjonsdatabasesystema. Java har støtte for låsbasert samtidighetskontroll – pessimistisk låsing … og no vi ska se litt nærmere på forskjellan mellom dissa to mekanisman.
Det handla om samtidighetsproblematikk – og I ska illustrere detta via det klassiske domenet: en pengeoverføring Her e den…
… med en tilhørende naiv implementasjon – pengan flyttes fra en fra-konto til en til-konto… en atomisk operasjon
Her er den naive implementasjonen av kontoen ->
One-liners inni deposit og withdraw ser veldig atomisk ut, men ->
… -> hvis vi ser på byte-koden til den naive konto-implementasjonen, ser vi at detta langt ifra e atomisk
Vi må legge på samtidighetskontroll for at dette skal fungere i nåkkå anna enn strengt single-threadede miljøer. Java støtter kun pessimistisk låsing out-of-the-box.
… for eksempel via denna pakken, som tilbyr et API for å begrense adgang til kodeblokker, altså låsing – og det på en meir fleksibel måte enn hva for eksempel synchronized –nøkkelordet gjør.
Her er en låsbasert pengeoverføring. I tillegg til involverte kontoa og beløp, har denne pengeoverføringsimplementasjonen også en Lock (en ReadWriteLock sådan) – og den legges rundt withdraw og deposit ., som e den kritiske regionen. Men det e ikkje nok!
- > Vi må også bruke samme lock til å låse alle åpne tilgjengelige tilstandsendrende metoder i konto-klassen. (Lock-implementasjonene i java.util.concurrency.locks-pakken er såkat reentrant – det vil si at hvis en tråd kun legger beslag på en lås én eneste gang, også om den eksplisitt blir bedt om å gjøre det flere ganger. Så den unngår å gå i dead-lock med seg selv – nåkkå som e fole unødvendig…)
Poenget mitt e at programmering med Locks ikke er trivielt, og har mange problemer/utfordringer
Vi kunne jo også distribuert låsen inn som en del av withdraw/deposit-metodene – men det forkludre modellen!
Poenget mitt e at programmering med Locks ikke er trivielt, og har mange problemer/utfordringer
Her har ikke MoneyTransfer sin egen lås, men basere se kun på Account-objektene sine – atomisiteten er ivaretatt. Denna koden funka i testan mine, men I syns nå at detta ser ut som ganske dead-lock-utsatt kode… Man tar en lås, for så vente på en anna en…
Poenget e at programmering med Locks ikkje e triviell.
SÅ, Software Transactional Memory, heretter kun kalt STM derimot…
I har kjørt to tester per implementasjon, dem røde kolonnan e testa med påtvungen trådskifte på verst tenkelige tidspunkt – blå kolonne e uten innblanding. Detta e test-kjøringa med ekstrem ”contention”.
Scenarioet der STM egna se e nåe man har et stort antall objekter som man jobbe mot. Da blir samtidighetskonflikter unntaket. Med kun én tråd så her STM bare overhead, men allerede med to tråder så bedra dette se … dessverre har ikkje laptopen her mer enn to kjerna – så flere tråder har I ikkje prøvd
Hvis dokker synes STM (og andre alternative samtidighetsmekanismer) høres interessant – gå å hør på Jonas Bonér i morgen – han tar opp STM mm – og setter skapet på plass med tanke på når STM egna se og ikkje!