Avatar billede scorp-d Nybegynder
19. maj 2008 - 22:02 Der er 10 kommentarer og
1 løsning

Hurtigste form for synkronisering af statisk variable

Hej..

Jeg har en statisk klasse med en statisk variable som skal tilgås meget ofte og derfor reagere rimelig hurtigt.

Men den statiske variable må kun tilgås af én tråd ad gangen.

Har hørt at der er store forskelle på hvor hurtigt C#’s synkroniseringsmetoder er, så ville bare høre hvad for en er den hurtigste til dette tilfælde?

På forhånd tak.
Scorp-D
Avatar billede scorp-d Nybegynder
19. maj 2008 - 22:04 #1
Skal lige siges at den variable er en hashtable....
Avatar billede arne_v Ekspert
19. maj 2008 - 23:02 #2
Proev med simpelt lock statement.

Med stor sandsynlighed performer det godt nok.
Avatar billede kodehoved Nybegynder
21. maj 2008 - 12:43 #3
Som arne_v siger, er lock et godt valg. lock resulterer i kald til Monitor-klassen, der er managed, så det går så hurtigt, som det kan (give'n'take). Husk at lock'e på noget fornuftigt - lav f.eks. et private object og lås på dette. BCL bruger flere steder lock(this) og lock(typeof(x)) - begge dele er en dårlig ide, da du risikerer at andre låser på det samme.

Har du brug for at flere kan læse men kun en kan opdatere ad gangen, kan du også se på ReaderWriterLock. Den vil i mange tilfælde give bedre performance, da den tillader flere samtidige læsere.

Brian
Avatar billede arne_v Ekspert
22. maj 2008 - 04:33 #4
Det er ihvertfald hvad MS's dokumentation siger.

http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx

Og de givne eksempler er rigtigt nok ikke optimale, men konklusionen om at create
en private member til at synkronisere på er efter min bedste overbevisning
ikke den rigtige løsning. Man bør synkronisere på det objekt som man vil tilgå. Det
princip virker både internt i samme klasse og mellem forskellige klasser plus
at det er let at læse og forstå.
Avatar billede kodehoved Nybegynder
22. maj 2008 - 07:27 #5
Der er jo ikke noget magisk ved selve det objekt man låser på. Det er blot en token, og derfor er der intet, der siger, at man skal synkronisere på det, man vil tilgå. Desuden holder den ide ikke altid i praksis, eftersom man kun kan låse på referencetyper.

Problemet er, at Monitor.Enter/Exit er statiske, og derfor har man brug for et eller andet at låse på. Et mere elegant løsning ville have været at oprette en instans af Monitor og låse på denne. Det har Microsoft desværre ikke gjort.

At låse på this er en dårlig ide, fordi man derved ikke har kontrol over hvem, der kunne finde på at låse på denne instans. Det kan føre til deadlocks. Problemet med at låse på typeof er det samme blot endnu mere udtalt.

At låse på tværs af klasser er som udgangspunkt en dårlig ide, da risikoen for deadlocks bliver meget større. Ideelt bør al tilgang til synkroniseret data foregå på en måde, hvor det er helt klart, hvem der kan tilgå data og hvorfra. Det gøres lettest ved at opretholde indkapsling. Af samme grund er det f.eks. uklogt at returnere referencer til interne data, da det åbner for samtidighedsproblemer.

Brian
Avatar billede arne_v Ekspert
24. maj 2008 - 04:55 #6
Der er måske ikke noget magisk ved objektet selv, men det har den unikke og hensigtsmæssige
egenskab at man har en reference til det alle de steder hvor man har brug for det.

Hvis man skulle få lyst til at låse på noget af en value type, så har man langt større
problemer end at man ikke kan gøre det.

Og det er et absolut must at man kan angive explicit hvad der skal lockes på, så
det er ikke muligt at bruge et behind the scene objekt.

Risikoeb for deadlocks bliver ikke større fordi det er forskellige klasser. Indkapsling er
naturligvis godt, men det er ikke p.g.a. samtidigheds problemer.
Avatar billede kodehoved Nybegynder
24. maj 2008 - 08:47 #7
Hej igen - enten taler vi meget forbi hinanden, eller også er vi bare slet ikke enige her.

Lad mig begynde med det sidste: Indkapsling har da i høj grad noget med samtidighedsproblemer at gøre. Hvis du kan indkapsle al tilgang til de kritiske områder i din types metoder, kan du jo netop være helt sikker på, at låsning sker på veldefinerede steder og dermed er det langt lettere at undgå deadlocks.

Hvis man omvendt - som du foreslår - tillader låsning på et offentlig objekt, har du ikke en chance for at vide hvem, der kunne finde på at låse på dette, og du er nødt til at se al din kode igennem for at finde låse. Til lukkede applikationer kan man måske gøre, som du foreslår, men hvis man som jeg laver frameworks, er det en virkelig dårlig ide ikke at have styr på, hvor der bliver låst. Og for applikationer ville jeg også foretrække at reducere, hvor der bliver låst.

Så skriver du desuden, at det er helt idioti at ville låse på en value type. Jeg har ingen interesse i at låse på en value type, men hvis man skal følge dit forslag om at låse på det objekt, man vil tilgå er det jo påkrævet, så lad os tage den.

For det første ser jeg intet odiøsst i at det er value types, der indeholder den tilstand, vi ønsker at opdatere og dermed sikre uddelt adgang til. Det kan f.eks. være en int. Har vi kun en af disse er Interlocked naturligvis oplagt, men den sikrer kun uddelt adgang til en enkelt variabel. Skal vi således opdatere to ints som en sammenhængende operation, har vi brug for noget mere. Her kan man naturligvis låse på this, men som nævnt er det med risiko for at andre har gjort det samme og dermed med risiko for deadlock.

Hvis du omvendt opretholder indkapsling, kan du placere dine låse der og så vil det være mere oplagt at bruge en intern instans som beskrevet i mit oprindelige indlæg.

Jeg kan godt blive lidt i tvivl om din forståelse af lock, når du skriver "og det er et absolut must at man kan angive explicit hvad der skal lockes på" - det objekt, man låser på, har absolut ingen indflydelse på låsningen. Objektet er blot en token. Det svarer til forsamlingshusprincippet med at den, der har mikrofonen har ret til at tale. Der er intet andet i det.

Hvis du har en type med to eller flere områder, der skal beskyttes i forskellige sammenhæng, er this desuden et dårligt valg, da den begrænser samtidigheden. Ved at have eksplicitte låse tilknyttet de forskellige områder opnås større samtidighed. Indrømmet er der en stor chance for at dette burde være to klasser, men ideen er god nok.

Tag evt. et kig på http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 for en gennemgang af låse og indkapsling.

Brian
Avatar billede scorp-d Nybegynder
25. maj 2008 - 11:12 #8
Wow der kom ligepludselig en del.... Men du kan bare smide et svar arne_v
Avatar billede arne_v Ekspert
01. juni 2008 - 04:26 #9
svar
Avatar billede arne_v Ekspert
01. juni 2008 - 04:57 #10
kodehoved>

Hvis man tillader låsning på public objekter, så er der ganske rigtigt en risiko
for deadlocks.

Men det er der jo standard metoder til at undgå.

Og det er jo langt bedre end alternativet - hvis man har brug for at låse på noget
og ikke gør det, så har man jo et problem - og som allerede forklaret en gang, så er selve
objektet selv det eneste alle har adgang til.

De value typer jeg refererede til var mutable user structs. Ved en int kan man have brug for at
lave et lock object. I de fleste tilfælde vil jeg tro at låsningen burde ske et
niveau længere ude. Men det er absolut et realistisk scenarie at skulle bruge et lock
objekt i.f.m. nogle simple data typer.

Og jeg forståe ikke at du bliver ved med at tale om this. Der er jo ikke nogen som har erklæret
sig uenige i at det er dårligt.

"Jeg kan godt blive lidt i tvivl om din forståelse af lock ..."

Se det forklarer jo nok i virkeligheden en del. Når man regner med at den anden er totalt idiot
så hæmmes ens evne til at læse og forstå hvad der skrives jo en hel del.

Der er ikke noget specielt ved .NET's locks. Det samme som Java's. Lidt mere
convenient men principielt det samme som Win32 threads, POSIX pthreads og
OpenVMS SYS$ENQ/SYS$DEQ. Plus alle dem jeg ikke kender.
Avatar billede kodehoved Nybegynder
01. juni 2008 - 16:23 #11
Jeg mener bestemt ikke, du er en idiot, og jeg beklager meget, hvis jeg skulle have givet dig anledning til at tro, at det er min opfattelse.

Min formulering har givetvis været uheldig, og det beklager jeg. Jeg reagerede på, at jeg opfattede dine formuleringer, som om at du tillægger selve det objekt, man låser på, speciel betydning og det håber jeg, vi kan blive enige om ikke er tilfældet.

Mht. låsning på offentlige objekter mener jeg (og ovennævnte bog, hvis du ikke vil tage mit ord for det) at det er langt bedre, at bruge indkapsling og dermed undgå at udstille låsen til offentligheden.

Laver man kode som andre skal kalde, mener jeg, at den metode er at foretrække frem for diverse konventioner om at brugerne skal overholde et bestemt låsemønster. Deri er vi, så vidt jeg kan forstå dig, ikke enige.

Jeg må indrømme, at jeg ikke er helt med på, hvad du mener om value types i denne sammenhæng. Jeg reagerede på, at du skrev "Hvis man skulle få lyst til at låse på noget af en value type, så har man langt større problemer end at man ikke kan gøre det." Det forstod jeg, som at du mente, at det var dumt at have behov for at synkronisere omkring value types. At dømme på dit seneste svar, ser det ud til at vi er enige om, at man sagtens kan have brug for synkronisering omkring både simple typer og brugerdefinerede structs. Så det er jo godt.

Så for at opsummere: som jeg læser det, lader det til, at vi har talt forbi hinanden. Vi er uenige om, hvorvidt det er en god ide at lave et eller flere dedikerede låseobjekter, men vi er enige om, at this er et dårligt valg, samt at man sagtens kan have brug for at synkronisere omkring value types.

Brian
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester