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.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
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; } } |