[disc/java] concurrency control instinker

Pagina: 1 2 Laatste
Acties:
  • 362 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Alarmnummer schreef op vrijdag 25 augustus 2006 @ 02:42:
[...]

In het voorbeeld heb ik duidelijk proberen te maken dat met een volatile write erin, het alsnog threadsafe zou worden

1) het is niet toegestaan om de write van a om te wisselen met b
2) het is niet toegestaan om de write van memory (van Bla naar een globaal veld bv) om te wisselen met de write van b
3) de waarde van a is zichtbaar door de publicatie functionaliteit van de volatile write van b

Hierdoor voorkom je dus dat een object partially constructed beschikbaar is in andere threads. En is de waarde van a zichtbaar binnen andere threads.

Zover ik begrepen heb hangt dit niet nog een keer weer af van de threading context waarin dit weer gebruikt gaat worden.

quote uit de desbetreffende faq "Under the new memory model, accesses to volatile variables cannot be reordered with each other or nonvolatile variable accesses"

[edit]
Om in happens before termen te blijven:
iedere access van volatile of non volatile variable a, die in de code voor volatile b staat, die heeft een happens before relatie.

iedere access van volatile b, die in de code voor volatile of non volatile c staat, die heeft een happens before relatie.

maw: de happens before relatie is er dus zeker :)
Volgens gaat voor het constructor voorbeeld punt 3 in theorie niet op, omdat "publicatie" alleen werkt als er zowel bij de read als de write een memory barrier is, en als je in een methode alleen iets met "a" zou doen in een andere thread dan raak je die niet. In de praktijk zul je (meestal?) wel gelijk hebben. Als het nieuwe object in een andere thread voor de eerste keer gebruikt zal worden dan moeten de waardes wel uit memory gelezen worden en heb je geen kans op stale data, dus het feit dat een tweede thread niet altijd een memory barrier over zou hoeven voor variabele "a" maakt dan niet meer uit.

De "happens-before" relatie is verder wel afhankelijk van of alle threads gebruik make van volatile members van hetzelfde object. Als één van de threads dat niet doet, dan is het niet thread-safe. Dus het voorbeeld nog een keer als foute variant (en beide blokken zijn methodes zodat er niet meer valsgespeeld kan worden met memory barriers ;)):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class VolatileExample {
  int x = 0;
  boolean y = false;
  volatile boolean v = false;
  public void writer() {
    x = 42;
    y = true;
    v = true;
  }

  public int reader() {
    if (y) { // v niet gebruikt, dus niet thread-safe    
      return x; // ook niet thread-safe, kan 0 of 42 zijn
    }
    return 0;
  }
}

Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
misfire schreef op vrijdag 25 augustus 2006 @ 15:00:
[...]
Volgens gaat voor het constructor voorbeeld punt 3 in theorie niet op, omdat "publicatie" alleen werkt als er zowel bij de read als de write een memory barrier is, en als je in een methode alleen iets met "a" zou doen in een andere thread dan raak je die niet. In de praktijk zul je (meestal?) wel gelijk hebben. Als het nieuwe object in een andere thread voor de eerste keer gebruikt zal worden dan moeten de waardes wel uit memory gelezen worden en heb je geen kans op stale data, dus het feit dat een tweede thread niet altijd een memory barrier over zou hoeven voor variabele "a" maakt dan niet meer uit.
Dat klopt. Maar as far as the constructor is concerned, hij heeft zijn taak gedaan.
De "happens-before" relatie is verder wel afhankelijk van of alle threads gebruik make van volatile members van hetzelfde object. Als één van de threads dat niet doet, dan is het niet thread-safe. Dus het voorbeeld nog een keer als foute variant (en beide blokken zijn methodes zodat er niet meer valsgespeeld kan worden met memory barriers ;)):
Tja.. en ik zeg dat die happens before relatie hier word afgedwongen door het feit dat we een volatile veld hebben en je instructies die eronder staan niet naar boven mag schoppen, en die er boven staan niet naar onderen mag schoppen. Dus ongeacht de threading context zal de happens before rules van volatile leiden tot een threadsafe class (afgezien van die 'a'-variable dus ook netjes uitgelezen moet worden en niet alleen netjes weggeschreven). Daarom zal het voorbeeld (afgezien van die a) dus altijd threadsafe zijn.

Voorbeeld uitgebreid
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
lass Bla{
   private int a;
   private volatile int b;

   public Bla(int a, int b){
      this.a = a;
      this.b = b;
   }

   public void foo(){
       int btemp = b;
       int atemp = a;
       System.out.println(btemp+" "+atemp)
   }
}


[edit]
Zelfs zonder de read van b zal a correct worden uitgelezen. Omdat a safely is published in de constructor en nog geen enkel thread een ref had naar een partially created object. Dus iedere andere thread zal de published versie zien van a, dus threadsafe.

[ Voor 25% gewijzigd door Alarmnummer op 25-08-2006 16:12 ]


Acties:
  • 0 Henk 'm!

  • misfire
  • Registratie: Maart 2001
  • Laatst online: 12-10-2024
Klopt helemaal, het ging mij alleen om de redenering. Volgens de specs werkt volatile alleen goed als alle threads het ook gebruiken (je moet reordering voorkomen én allemaal een memory barrier over voordat een "happens-before" relatie kan worden gegarandeerd).

In de praktijk lijk je met jouw voorbeeld in de constructor voor een safe situatie te zorgen zónder dat meerdere threads per sé volatile gebruiken... Tenzij er nog haken en ogen zijn aan dit voorbeeld waar wij allebei nog niet aan hebben gedacht? Het is in ieder geval niet een gebruik van volatile op de manier zoals het ontworpen is, dus ik ben er niet helemaal gerust op dat ook hier (net als bijv DCL) toch stiekem nog ergens een addertje zit... Ik ben benieuwd of men in de mailing list jouw voorbeeld kan bewijzen als een geldige oplossing! :)

Acties:
  • 0 Henk 'm!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
misfire schreef op vrijdag 25 augustus 2006 @ 16:51:
Klopt helemaal, het ging mij alleen om de redenering. Volgens de specs werkt volatile alleen goed als alle threads het ook gebruiken (je moet reordering voorkomen én allemaal een memory barrier over voordat een "happens-before" relatie kan worden gegarandeerd).

In de praktijk lijk je met jouw voorbeeld in de constructor voor een safe situatie te zorgen zónder dat meerdere threads per sé volatile gebruiken... Tenzij er nog haken en ogen zijn aan dit voorbeeld waar wij allebei nog niet aan hebben gedacht? Het is in ieder geval niet een gebruik van volatile op de manier zoals het ontworpen is, dus ik ben er niet helemaal gerust op dat ook hier (net als bijv DCL) toch stiekem nog ergens een addertje zit... Ik ben benieuwd of men in de mailing list jouw voorbeeld kan bewijzen als een geldige oplossing! :)
Voor de rest van de mensen... dit is puur een theoretisch issue.. Niemand moet zulke code schrijven om iets threadsafe te maken. Het is puur een middel om onze gedachten duidelijk te krijgen.
Pagina: 1 2 Laatste