03. juli 2011 - 21:31Der 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å?
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.
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.
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 :-)
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.
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. ;-)
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.
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ø :-)
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.
#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.
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).
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.
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.
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.