Avatar billede gonnemand Nybegynder
03. juli 2011 - 21:31 Der er 20 kommentarer og
1 løsning

Lock(object) - forespørgelser

Hey experter.

Jeg har en metode:

private static readonly object _locker = new object();

public void myMethod()
{
  lock(_locker)
  {
      // Do something;
  }
}

Jeg vil gerne kunne "spørge" på, om der er "låst". Dette kan selvfølgelig opnås med en boolean der bliver sat, men findes der en mere korrekt måde?

Yderligere, vil jeg gerne kunne se om og hvor mange der er i "kø". Jeg ville nok kunne gøre dette, ved at add'e til en liste, lige før lock(_locker), og remove'e fra listen som det sidste i lock'en.

Men men men... vil overnævnte være kode-mæssigt korrekt?
Findes der andre, måske mere korrekte, måder at opnå disse ting på?

PFH tak :-)
Avatar billede arne_v Ekspert
03. juli 2011 - 21:37 #1
lock keyword giver ikke saa meget kontrol over den slags.

Ved at bruge Monitor Enter/TryEnter/Exit metoderne kan du ihvertfald se om den er laast.

Hvor mange der er i koe vil nok kraeve en liste.
Avatar billede arne_v Ekspert
03. juli 2011 - 21:38 #2
Generelt boer man proeve og loese sit egentlige problem paa en anden maade end den her slags low level locking - risikoen for fejl er simpelthen for stor.
Avatar billede gonnemand Nybegynder
03. juli 2011 - 21:54 #3
Okay... har du et forslag til anden løsning?

Det hele ligger i en wcf service, hvor den låste metode bliver kaldt fra:

[OperationContract]
object GetSomeInfo()
{
  myObject();
}

Så jeg har ikke umiddelbart nogen kontrol over trådene.

Jeg sidder ikke med koden her, så derfor bruger jeg kode eksempler :-P
Avatar billede arne_v Ekspert
03. juli 2011 - 22:00 #4
Ja.

Men hvad er der som goer at du har brug for at vide om objektet er laast og hvor mange som venter?
Avatar billede gonnemand Nybegynder
04. juli 2011 - 06:08 #5
WCF servicen bliver kørt gennem en windows service.
Derfor skal jeg i Stop() og Pause() metoderne i windows servicen, tjekke om der er nogen tråde igang. Der er nemlig tale om read og write til database.

Hvis der er en tråd igang, skal den have lov til at kører færdig, og dem som står i kø, skal ikke have lov til at komme ind.
Avatar billede mcb2001 Nybegynder
04. juli 2011 - 13:16 #6
jeg har selv en idé til hvordan jeg ville løse denne, nemlig med at køre alle som workers under en hovedtråd, lukke køen, afvente et givent timeout og hvis de ikke afslutter inden, så lukke dem. Desuden bør ens database skrivninger foregå i transactions, så hvis den ikke gennemføres komplet, så skal SQL'en selv rulle tilbage.

Men jeg vil også gerne høre hvad Arne foreslår, det plejer ikke at være helt skidt :-)
Avatar billede Syska Mester
04. juli 2011 - 15:30 #7
Dvs du låser så 2 ikke kan skrive/læse på samme tid ?

Overstående giver lidt mening, hvis du har en timestamp eller andet som sikre dig at nummer 2 i køen til at skrive ikke kan overskrive det data nummer 1 skrev, fordi den timstamp havde ændre sig.

Læse er der vel ingen grund til at lave locking på.

Lyder mere som om du prøver at løse et problem du ikke har ...

Der er: Monitor, Semaphore og Mutex til at læse tråde i .NET, alle med forskellige egenskaber.

mvh
Avatar billede gonnemand Nybegynder
04. juli 2011 - 18:47 #8
Bruger faktisk monitor nu.
Og i OnStop() kalder jeg monitor.enter på samme objekt samt sætter en boolStopping = true således at de tråde der er i kø, returnere noget brugbart til clienterne der har kaldt web servicen.
Det fungere umiddelbart efter hensigten, men skal have det testet noget mere.

Men ja, altid godt at få Arnes mening ;-)
Jeg er nød til kun at lade én tråd køre igennem ad gangen, da det som én tråd MÅSKE gemmer, kan have indflydelse på hvad næste tråd skal returnere og MÅSKE skal gemme. ;-)
Avatar billede Syska Mester
04. juli 2011 - 19:03 #9
husk at SQL overholder ACID:
http://en.wikipedia.org/wiki/ACID

Dvs hvis der kommer en klient og vil opdatere række A, så laver den en lock. Dvs kommer der en og vil læse, må den pænt vente til den første er færdig med at skrive.

Derfor burde det være unødvendig at lave din egen lock, da database nok skal klare det for dig.

Jeg kan se problemet hvis 2 vil opdatere den samme række, men det er et helt andet problem.

mvh
Avatar billede gonnemand Nybegynder
04. juli 2011 - 19:58 #10
der er ingen opdateringer, kun læsning og skrivning som beskrevet i #8

Prøver om jeg kan poste kode eksempler i morgen... og evt. en bedre forklaring ;-)
Avatar billede Syska Mester
04. juli 2011 - 20:20 #11
Nej, der skrev du at du gemte data, det kan i min verden være 2 ting :-) ... men point taken, nu er jeg klar over du laver inserts.

Men hvis Insert er færdig, så får den næste jo også det rigtige data tilbage.

Det virker i min verden lidt mærkeligt at alle skal lide under at du kun vil have en operation i gang.

Måske kunne det laves lidt mere intelligent, så hvis der kommer et Insert/Update ... så laver den en lock ... som forhindre readers til at læse, før end den Insert/Update er færdig. Dermed har du ikke et delay hvis der kun er readers i kø :-)

mvh
Avatar billede mcb2001 Nybegynder
04. juli 2011 - 21:11 #12
ellers kan du lave ét objekt der skriver til databasen, og så lave lock på dette objekt hver gang du ved der skal skrives en eller flere ting fra samme tråd.
Avatar billede gonnemand Nybegynder
04. juli 2011 - 21:49 #13
#11
Forstår godt din tankegang, men alle readers er potentielle writers... alt efter hvilke data der kommer ind via servicen og hvad der står i databasen.

Yderligere så kan det en tråd skriver, være afgørende for om en anden tråd skal gemme data eller ej. Derfor er det nødvendigt, at kun én tråd afgangen får lov til at læse... og skrive, hvis dette skulle være tilfældet.

Problemet ligger i at, f.eks. tråd_1 og tråd_2 potentielt kan indeholde 100% samme data... så hvis tråd_1 får lov til at skrive, mens tråd_2 er ved at læse og deres data ikke findes i DB, så gemmer tråd_1 mens tråd_2 læser.
Tråd_2 læser jo så, at dens data ikke ligger i DB, og vil også gemme dens data. Men når den så vil til at gemme, fejler det, da data lige er gemt af tråd_1.

Giver det mening.... :-P
Avatar billede Syska Mester
04. juli 2011 - 21:56 #14
Er det ikke bare et spm om lave din sql statement på en anden måde?

UPDATE table SET col = 'colvalue' where col = 'oldcolvalue';

Hvis der er flere columns, så ville jeg tilfælde dem yderligere.

Overstående burde give et antal affected rows ... og deraf kan du se om der er sket en update.

Måske dette kan løse dit problem ?

Nu kender vi snart hele context af dit problem :-). Før virkede det som om du har en method der læse og en som skrev.
Avatar billede Syska Mester
04. juli 2011 - 21:58 #15
Men igen ... overstående kan du også løse ved at pakke det hele ind i en sql transaction.

Dermed holder tramsactions styr på din locking du efterlyser.

mvh
Avatar billede arne_v Ekspert
05. juli 2011 - 03:13 #16
Hvis der kun udfoeres enkelt SQL statement opdateringer i databasen databasen soerger for at databasen er konsistent.

Hvis der udfoeres multi SQL statement opdateringer i databasen og dun bundter dem i samme database transaktion vil databasen stadig soerge for at databasen er konsistent (enten udfoers alle eller ingen af saetningerne).
Avatar billede arne_v Ekspert
05. juli 2011 - 03:17 #17
Hvis du vil have helt programmatisk styr paa hvad der sker saa kan du lave en singleton hvor traade registrerer sig naar du starter og afregistererer sig naar de er faerdige. Metoderne skal saa lock'e paa et field saa den er thread safe.

Saa kan du hente hvor mange traade der er igang med at koere.
Avatar billede arne_v Ekspert
05. juli 2011 - 03:19 #18
Men er det noedvendigt?

Jeg antager at din ServiceBase OnStop metode kalder ServiceHost Close.

Og docs for den siger:

This method causes a CommunicationObject to gracefully transition from any state, other than the Closed state, into the Closed state. The Close method allows any unfinished work to be completed before returning.


Er det ikke den funktionalitet du efterspoerger?
Avatar billede arne_v Ekspert
08. august 2011 - 00:58 #19
Tid at faa afsluttet her?
Avatar billede gonnemand Nybegynder
15. juni 2012 - 09:40 #20
Løsningen blev arne_v's første svar, som er utrolig nem at bruge.

Så send et svar arne_v så denne tråd kan afsluttes :-)
Avatar billede arne_v Ekspert
15. juni 2012 - 15:41 #21
svar
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

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