Side 1 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006



Like dokumenter
INF1010 Tråder J. Marit Nybakken Motivasjon. Å lage en tråd

Argumenter fra kommandolinjen

2 Om statiske variable/konstanter og statiske metoder.

TDT4100 Objektorientert programmering

UNIVERSITETET I OSLO

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

Synkronisering I. Kapittel 6. Tråd A. ferdig. t.varsle() u.vente() Tråd B. ferdig. tid

INF 1000 høsten 2011 Uke september

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

INF2440 Prøveeksamen, løsningsforslag, 20 mai Arne Maus PSE, Inst. for informatikk

INF1000 undervisningen INF 1000 høsten 2011 Uke september

Programmering i C++ Løsningsforslag Eksamen høsten 2005

Synkronisering II. Kapittel 7. Betingelse oppfylt (0) liste. tråd-deskriptor. venteliste. tråd-deskriptor. tråd-deskriptor.

La oss begynne med en repetisjon av hva som skjer når du kjører Javaprogrammet

EKSAMENSFORSIDE SKRIFTLIG EKSAMEN

UNIVERSITETET I OSLO

I et Java-program må programmøren lage og starte hver tråd som programmet bruker. Er dette korrekt? Velg ett alternativ

GUI («Graphical User Interface») del 2

Løsningsforslag ukeoppg. 6: 28. sep - 4. okt (INF Høst 2011)

UNIVERSITETET I OSLO

Sortering med tråder - Quicksort

UNIVERSITETET I OSLO

INF1010 Tråder II 6. april 2016

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

2 Om statiske variable/konstanter og statiske metoder.

Dagens tema: 12 gode råd for en kompilatorskriver

Eksamen INF1010 V2009 Del B prøveeksamen V2010 Vekt 60 %

INF1000 Metoder. Marit Nybakken 16. februar 2004

Tråder Repetisjon. 9. og 13. mai Tråder

Socket og ServerSocket

UNIVERSITETET I OSLO

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

UNIVERSITETET I OSLO

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

Forkurs INF1010. Dag 1. Andreas Færøvig Olsen Tuva Kristine Thoresen

Tittel Objektorientert systemutvikling 1. Eksamenstid, fra-til Ant. oppgaver 6

Feilmeldinger, brukerinput og kontrollflyt

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Metoder med parametre, løkker og arrayer

INF1010 våren januar. Objektorientering i Java

Velkommen til. INF våren 2016

Dagens forelesning. Java 13. Rollefordeling (variant 1) Rollefordeling (variant 2) Design av større programmer : fordeling av roller.

UNIVERSITETET I OSLO

IN1010 våren januar. Objektorientering i Java

Fra Python til Java. En introduksjon til programmeringsspråkenes verden. Dag Langmyhr

INF1000 (Uke 15) Eksamen V 04

INF1000 (Uke 15) Eksamen V 04

UNIVERSITETET I OSLO

Oversikt. INF1000 Uke 1 time 2. Repetisjon - Introduksjon. Repetisjon - Program

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

INF1010, 22. mai Prøveeksamen (Eksamen 12. juni 2012) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

INF2440 Eksamen 2016 løsningsforslag. Arne Maus, PSE ifi, UiO

OBJEKTER SOM EN PROGRAMMERINGS-TEKNIKK

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

class Book { String title; } class Dictionary extends Book { int wordcount; } class CartoonAlbum extends Book { int stripcount; }

Løsnings forslag i java In115, Våren 1996

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

Fra Python til Java, del 2

INF1000: Forelesning 6. Klasser og objekter del 1

Introduksjon til objektorientert. programmering. Hva skjedde ~1967? Lokale (og globale) helter. Grunnkurs i objektorientert.

INF1010 Sortering. Marit Nybakken 1. mars 2004

Forelesning inf Java 5

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

En algoritme for permutasjonsgenerering

Mer objektorientert programmering

Forelesning inf Java 5

Forklaring til programmet AbstraktKontoTest.java med tilhørende filer Konto.java, KredittKonto.java, SpareKonto.java

Arv. Book book1 = new Book(); book1. title = "Sofies verden" class Book { String title; } class Dictiona ry extends Book {

LC191D Videregående programmering Høgskolen i Sør-Trøndelag, Avdeling for informatikk og e-læring. Else Lervik, januar 2012.

Konstruktører. Bruk av konstruktører når vi opererer med "enkle" klasser er ganske ukomplisert. Når vi skriver. skjer følgende:

INF1000 (Uke 5) Mer om løkker, arrayer og metoder

INF1010 Repetisjonskurs i tråder

Java PRP brukermanual

Gjennomgang av eksamen H99

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister Videre

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Prøveeksamen INF2440 v Arne Maus PSE, Inst. for informatikk

IN1010 våren Repetisjon av tråder. 15. mai 2018

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

Innhold. Forord Det første programmet Variabler, tilordninger og uttrykk Innlesing og utskrift...49

UNIVERSITETET I OSLO Det matematisk-naturvitenskapelige fakultet

Programmeringsspråket C

Tråder Repetisjon. 9. og 13. mai Tråder

IN våren 2018 Tirsdag 16. januar

GetMutex(lock) { while(testandset(lock)) {} } En context switch kan ikke ødelegge siden testen og endringen av lock skjer i samme instruksjon.

Eksempel 1 Eksempel 2 Dramatisering. INF1000 uke 3. Sundvollen 7. september 2015 Dag Langmyhr. INF1000 Sundvollen

IN våren 2019 Onsdag 16. januar

INF våren 2017

Oppgave 3 a. Antagelser i oppgaveteksten. INF1020 Algoritmer og datastrukturer. Oppgave 3. Eksempelgraf

Klasser, objekter, pekere og UML. INF gruppe 13

OO-eksempel. Modellen ser slik ut: Studenter + antstudenter : int = 0

Stein Gjessing. Institutt for informatikk. Universitetet i Oslo. Institutt for informatikk

Avdeling for ingeniørutdanning Institutt for teknologi

MAT-INF 1100: Obligatorisk oppgave 1

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Kort om meg. INF1000 Uke 2. Oversikt. Repetisjon - Introduksjon

Transkript:

Side 1 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 Prosesser og tråder Datamaskinen lager prosesser. En prosess organiserer arbeidet i et program ved å administrere tråder. Det er derfor alltid minst en tråd i et program. Det kan vi sjekke med følgende lille program: public class A_Test { public static void main(string[] args) { System.out.println("Aktive tråder:"+thread.activecount()); Denne koden og eventuelle utvidelser i form av flere kodelinjer og klasser, vil høre til den første tråden. Men det er også mulig å lage nye tråder med utgangspunkt i den første tråden. Tråder i Java Det er enkelt å lage nye tråder i Java. Enhver klasse som spesialiserer klassen Thread, blir en tråd når den instansieres. Tråden settes klar for kjøring med meldingen start(). Når tråden er satt klar for kjøring, får den etter en stund meldingen run fra den noden den er klargjort i. Denne noden er nesten alltid JVM. public class EnTraad extends Thread { System.out.println( Hello world ); Thread t = new EnTraad(); t.start(); Men det kan kreve litt mer planlegging å bruke trådene riktig. Planlegging kombinert med deklarasjonen synchronized når det er nødvendig, kan føre til programmer som oppfører seg riktig i de fleste kjøremiljøer. Synkronisering Ordet synchronized brukes for å deklarere områder som skal holde monitoren i et objekt. Det å holde monitoren betyr å ha enerett på ressursene i objektet. Ordet synchronized kan brukes på metoder og på områder inne i en metode, men med litt ulik syntaks. Bruksområde Flere tråder vil operere på de samme ressursene. Utfordring Når flere vil forandre en ressurs, må selve forandringsarbeidet beskyttes mot feil. Feil kan oppstå når to tråder prøver å endre en felles ressurs samtidig. Selve det å forandre en ressurs

Side 2 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 må beskyttes, slik at hver tråd alltid opererer med korrekt datagrunnlag. Problemet er knyttet til begrepet race condition. Race condition Oppdatering av en ressurs baseres av og til på eksisterende verdi, som når verdien i en variabel skal økes i stedet for bare å settes. Skal endringen være i forhold til nåværende verdi, må operasjonen foregå i flere trinn. Først må verdien leses, deretter må den økes og til slutt lagres tilbake før noen andre har rukket å lese, øke, eller legge den tilbake. Prosessen med å lese, øke og lagre tilbake må være atomisk, som betyr udelelig. Hvis den ikke er atomisk oppstår en race condition. En mutator kan gjøres atomisk ved å deklarere den med synchronized. Det som skjer er at objektet som kaller en synkronisert metode, anvender sin lock, eller lås, på alle synkroniserte metoder i objektet. Så lenge dette objektets lock er assosiert med tjenerobjektet, kan ingen andre objekter slippe til i objektets synkroniserte metoder. Klassemetoder har en parallell mekanisme basert på en instans av Class. Eksempler Alle eksemplene oppfører seg forskjellig på ulike maskiner, og under ulike stressnivåer på hver maskin. Eksempel 1 I disse eksemplene deklareres variabelen n i trådklassen med static, og kan derfor brukes som en felles ressurs. I eksemplene er n i utgangspunktet ikke beskyttet mot race conditions. public class B_Sync extends Thread { static int n = 1; for (int i = 1; i <= 10; i++) { System.out.println(n); n = n + 1; Thread thr1 = new B_Sync(); Thread thr2 = new B_Sync(); thr1.start(); thr2.start(); Klassen B_Sync inneholder en race condition. Ved kjøring kan det være vanskelig å påvise feil, selv ved å legge inn stressfaktorer.

Side 3 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 Ved å legge til ordet this i utskriften, får vi vite hvilken tråd som skriver ut for øyeblikket. Selve utskriften, println, er beskyttet mot race conditions, men ikke før argumentene er beregnet. System.out.println(n+ " "+this); Dette lar oss følge med på hvilken tråd som gjør hva. Hvis maskinen som tester klassen ikke gjør feil, kan grunnen være at den ene tråden blir så raskt ferdig at den allerede har stoppet når den andre begynner. Dermed går de selvsagt ikke i veien for hverandre. Det kan altså noen ganger være vanskelig å få påvist race condition, dersom det ikke settes inn kode som forsinker trådene litt ujevnt. public class C_Sync extends Thread { static int n = 0; boolean w = true; for (int i = 1; i <= 10; i++) { if (w =!w) { sleep(10); catch (InterruptedException e) { System.out.println(n+" "+this); Thread thr1 = new C_Sync(); Thread thr2 = new C_Sync(); thr1.start(); thr2.start(); Dette forsinker annenhver iterasjon i metoden run. Dersom et objekt rekker å gjøre to iterasjoner, er det altså sikret en forsinkelse. Denne ujevnheten kan være nok til å påvise race condition i et gitt testmiljø. Siden vi ikke har kontroll med hvilket objekt som kaller run i en Thread, vil vi ikke bruke run til å teste synchronized. Vi lager heller en metode for å øke verdien i n. Vi deklarerer derfor en mutator for ressursen. Se metoden incr. public class D_Sync extends Thread { static int n = 0; static void incr(d_sync sync) { System.out.println(n+" "+sync); n++;

Side 4 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 boolean w = true; for (int i = 1; i <= 10; i++) { if (w =!w) { sleep(10); catch (InterruptedException e) { incr(this); Thread thr1 = new D_Sync(); Thread thr2 = new D_Sync(); thr1.start(); thr2.start(); En klasse som D_Sync kan inneholde en race condition. Ved kjøring kan det være vanskelig å påvise feil, selv ved å legge inn stressfaktorer. Vi kan imidlertid legge inn argumentet this i kallet til incr, for å finne ut, for å finne ut hvilken tråd som er aktiv for øyeblikket. Selv om trådene opererer i ujevn rekkefølge, er det ikke gitt at vi kan påvise race condition, selv om vi vet at risikoen er der. En grunn kan være at vi rett og slett ikke tester mange nok ganger. Eksempel 2 For å legge bedre til rette for å påvise race condition, kan vi bygge et litt mer strukturert og sammensatt programsystem. Som ellers i objektorientert programmering, skiller vi klassene slik at vi oppnår høyere kohesjon, som betyr større konsentrasjon og sammenheng i oppgavene. Først skilles entry point fra testklassene, slik at det blir lettere å kontrollere inngangsverdier, parametre og etterbehandling. public class A_Entrypoint { static final int antall = 25; for (int j = 0; j < antall; j++) { new A_Synchronize().start(); Med et slikt startpunkt kan vi enkelt regulere antall ganger testen skal kjøres, uten at den egentlige testkoden blir mer komplisert. Ved å øke antallet testkjøringer øker sannsynligheten for å kunne påvise race condition. Selve testkoden vises i klassen A_Synchronize.

Side 5 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 public class A_Synchronize extends Thread { static int n = 0; static void incr() { System.out.println(n); for (int i = 1; i <= 10000; i++) { float f = 2; f = f * f; f = f / f; for (int i = 1; i <= 10000; i++) { float f = 2; f = f * f; f = f / f; n++; for (int i = 1; i <= 10; i++) { incr(); Denne versjonen kan stresse prosessen en del, og problemet er denne gangen at det er vanskelig å sjekke dataene med println, fordi det krever for mye menneskelige ressurser å kontrollere så mange datarader. Strategien videre er å bygge et array med Color som enkelt kan etterbehandles i et grafisk vindu. Dette legges det til rette for ved å fortsette å skille ut kode, denne gangen ved å skille logikk og databehandling fra presentasjon. Setningene med println påvirker i seg selv resultatet av testene, og bør helst erstattes med andre testmetoder. Variabelen n skal ikke lenger være statisk, men en objektressurs. Eksemplet er altså blitt mer objektorientert. Den nye strategien er dermed gunstig i forbindelse med flere prinsipper i objektorientert programmering. public class B_Entrypoint { static final int COUNT_OF_THREADS = 150; static final int ITER_THREAD = 10; new B_ClientTester(); Her får B_Entrypoint oppgaven å sentralisere to testparametre. Dette gjør det enkelt og oversiktlig å variere antall tråder og antall iterasjoner i hver tråd, for å kalibrere testen til det maskinmiljøet testen skal kjøres i. Selve test-programmet og den felles ressursen n er i B_ClientTester.

Side 6 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 public class B_ClientTester { int n = 0; Color[] p = new Color[B_Entrypoint.ITER_THREAD * B_Entrypoint.COUNT_OF_THREADS]; boolean w = false; public B_ClientTester() { for (int j = 0; j < B_Entrypoint.COUNT_OF_THREADS; j++) { new B_Client(this).start(); new Proof(p); void incr(object o) { p[n] = Color.GREEN; if (w =!w) if (n % 3 == 0) Thread.sleep(5); catch (InterruptedException e) { System.out.println(n+" "+o); n++; Hver gang incr besøkes, oppdateres arrayet med fargen GREEN i det punktet variabelen n peker på for øyeblikket. Dersom n har samme verdi som ved et tidligere besøk, skyldes dette en race condition. Dette vil resultere i at enkelte elementer i arrayet ikke oppdateres med fargen GREEN. Den som foretar besøk og operasjoner på den felles ressursen, er objekter fra klassen B_Client. public class B_Client extends Thread { B_ClientTester caller; public B_Client(B_ClientTester synctester) { this.caller = synctester; for (int i = 1; i <= B_Entrypoint.ITER_THREAD; i++) { caller.incr(this); Selv om koden er blitt mer sammensatt, er det er fortsatt minst like enkelt å regulere antall tester. Nå spares testresultatet i variablen p, som kan presenteres grafisk etter at dataene er samlet opp. Presentasjonen gjøres i klassen Proof. public class Proof extends JFrame { public Proof(Color[] p) { settitle("race condition examination");

Side 7 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 setsize(500, 400); getcontentpane().setbackground(color.gray); setlocationrelativeto(null); int l = (int) Math.sqrt(p.length); setlayout(new GridLayout(l, 0, 1, 1)); for (Color c : p) { JPanel r = new JPanel(); r.setbackground(c); add(r); setvisible(true); Nå er det atskillig enklere å påvise race conditions. Det er altså vanskelig å påvise race conditions med for få testkjøringer. Nesten 300 kjøringer måtte til før den første feilen kom i akkurat dette miljøet. I andre miljøer og med andre stressfaktorer, som ikke trenger å komme fra testprogrammet, kan det kreves mange flere iterasjoner før det kan påvises feil. Men ett problem gjenstår. Legg merke til at den siste delen av denne kjøringen viser utelukkende feil. Siden dette er et stort sammenhengende område, tyder det på at det også har oppstått en annen feil enn race conditions. Feilen er at ikke alle trådene rakk å bli ferdige før testresultatet ble vist. Testresultatet må altså ikke vises før alle trådene er ferdige med sine operasjoner. Denne feilen oppdages ikke i alle maskinmiljøer. Dersom en gitt maskin har ressurser som gjør at alle trådene rekker å bli ferdige før resultatet vises, kan ikke utvikleren oppdage feilen. Dersom testen i det viste miljøet hadde stoppet på rad 23, ville ikke feilen vært oppdaget her heller. Testklassen må derfor modifiseres, slik at den venter på at alle trådene blir ferdige før resultatet kan vises riktig.

Side 8 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 public class B_ClientTester { int n = 0; Color[] p = new Color[B_Entrypoint.ITER_THREAD * B_Entrypoint.COUNT_OF_THREADS]; boolean w = false; public B_ClientTester() { for (int j = 0; j < B_Entrypoint.COUNT_OF_THREADS; j++) { new B_Client(this).start(); while (Thread.activeCount()!= 1) { Thread.sleep(200); catch (InterruptedException e) { new Proof(p); void incr(object o) { p[n] = Color.GREEN; if (w =!w) if (n % 3 == 0) Thread.sleep(5); catch (InterruptedException e) { System.out.println(n+" "+o); n++; Ved å sjekke Thread.activeCount kan vi regne alle trådene som ferdige når det bare er en tråd igjen. Ved å bruke sleep, parkeres testtråden i 200 ms uten å bruke ressurser. Det neste resultatet ser derfor mer rimelig ut.

Side 9 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 I denne versjonen av B_ClientTester er det mulig å variere mod-faktoren, sleep-verdien så vel som antall tråder, for å se variasjoner i forekomsten av race conditions i akkurat det miljøet der testingen foregår. Ved å deklarere incr med synchronized, skal neste testkjøring vise utelukkende grønne felt, fordi alle mulige varianter av n har pekt på testarrayet. Vær oppmerksom på at også arrayet p er utsatt for race conditions. Eksempel 3 Det kan av og til være utfordrende å observere race conditions på en kontrollert måte. Av og til er testen i seg selv utsatt for race conditions. En strategi for å kontrollere dette, er å bruke innkapsling for å konstruere objektverdier parallelt med felles ressurser. Hver gang et objekt (altså en tråd) vil oppdatere en felles ressurs, må det også oppdatere sin egen innkapslede ressurs. Den innkapslede ressursen er nemlig ikke utsatt for race conditions. Når alle trådene er ferdige, kan moderobjektet sammenligne sin felles ressurs med summen av alle trådenes ressurser. Dersom det ikke har oppstått feil pga race conditions underveis, og alle trådene er helt ferdige med sine arbeidsoppgaver, skal disse verdiene være like. Vi lager en isolert inngang til programmet: public class Entrypoint { public static final int COUNT_OF_THREADS = 2000; public static final int ITER_THREAD = 500; static final int COUNT_OF_TESTS = 10; public static void main(string[] args) { for (int i = 0; i < COUNT_OF_TESTS; i++) new ClientTester(); Dette testoppsettet er litt anderledes enn de tidligere eksemplene. I tillegg til den felles ressursen n, er det også laget en testvariabel, testsum. I dette eksemplet lar vi i tillegg hver tråd sende en egen melding, countdown, til modertråden når de er ferdige. Modertråden teller hvor mange som er ferdige, og går videre når alle trådene er ferdige med sitt arbeid. Denne tellingen er også utsatt for race conditions, og må altså beskyttes med synchronized. public class ClientTester { int n; int testsum; int activethreads; synchronized void countdown() { activethreads--;

Side 10 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 Client[] a = new Client[Entrypoint.COUNT_OF_THREADS]; public void incr() { n++; public ClientTester() { n = 0; testsum = 0; activethreads = Entrypoint.COUNT_OF_THREADS; System.out.println("Starter synkrontest"); for (int i = 0; i < Entrypoint.COUNT_OF_THREADS; i++) { a[i] = new Client(this); if (r.nextboolean()) { a[i].setpriority(thread.min_priority); a[i].start(); while (activethreads > 0){ Thread.sleep(500); catch (InterruptedException e) { for (Client t : a) { testsum += t.get(); System.out.println("Ferdig!\tFelles ressurs: " + nf.format(n) + "\tkontroll: " + nf.format(testsum)+"\n"); NumberFormat nf = NumberFormat.getInstance(); I enkelte testmiljøer viser det seg at denne testen ikke viser race conditions. Problemet er likevel til stede, ikke minst fordi feilen viser seg på andre maskiner. Vi kan bruke en variabel i incr for å oppdage at metoden har besøk av flere objekter på samme tid. Det er nettopp dette som fører til race condition, og som kan unngås med synchronized. For å kunne påvise race conditions på maskiner som ikke viser feilen med denne testkoden, kan du legge inn for eksempel denne incr metoden i stedet: boolean w = false; public void incr() { int i = n; if (w =!w) if (n % 1000 == 0) Thread.sleep(5); catch (InterruptedException e) { n = i + 1;

Side 11 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006 Her deler vi opp lesing, beregning og skriving av n for å provosere fram feil ved race conditions. I praktiske algoritmer er det helt vanlig at objekter som skal muteres, gjør tilsvarende arbeid i flere trinn. En maskin som aldri viser race conditions med den enkle versjonen av algoritmen, kan få store feil med den mer sammensatte algoritmen. Her er et eksempel på resultater etter usynkronisert bruk av den sammensatte algoritmen: Starter synkrontest Venter på at alle skal bli ferdige Ferdig! Felles ressurs: 460 Kontroll: 1 500 Starter synkrontest Venter på at alle skal bli ferdige Ferdig! Felles ressurs: 530 Kontroll: 1 500 Starter synkrontest Venter på at alle skal bli ferdige Ferdig! Felles ressurs: 510 Kontroll: 1 500 Synkronisert bruk av den samme algoritmen foregår uten forskjeller i felles og kontrollert ressurs. Uten den forstyrrende koden i incr oppstod det heller ikke forskjeller ved ikke-synkronisert bruk på en bestemt datamaskin. Men dette endrer seg fra maskin til maskin, og med ulike belastninger på hver maskin.