Sorry about the mistake in the test... I am sick at the moment and not
the sharpest.

Stuart; Thanks for the insights, and happy to see you are around here...

Niclas

On Fri, Aug 26, 2011 at 2:08 PM, Stuart McCulloch <[email protected]> wrote:
> On 26 Aug 2011, at 06:45, Niclas Hedhman wrote:
>
>> But if you are saying that volatile.get() has the same effect as
>> synchronized{} enter, and the volatile.set() the effect of
>> synchronized{} exit (i.e. the cache is invalidated and flushed
>> respectively), then why is there a performance boost?
>
> synchronized is not just a memory barrier - it's a lock so it may involve 
> context-switching of threads, parking, etc.
>
> Modern JVMs use adaptive-spinning which helps with short-lived synchronized 
> (at least comparing Java6 to Java5), but there's definitely an added cost - 
> whereas memory fences (LoadLoad, etc.) are provided at the machine code level 
> and aren't as costly as you might think
>
> That's also why in Java5 ReentrantLock was always faster than synchronized 
> regardless of the contention level. It's only thanks to performance 
> improvements in the JVM that synchronized is once again as fast as 
> ReentrantLock for low levels of contention (but it's still not as good at 
> high-levels of contention and also isn't guaranteed to be "fair", whereas you 
> can ask for a fair ReentrantLock to avoid starvation).
>
>> I assumed that volatile only marked that particular memory location to
>> be guaranteed to be updated, hence keeping most of the cache intact,
>> thus a huge boost over synchronized.
>>
>> And the example (second link) is even more remarkable;
>>
>> class VolatileExample {
>>  int x = 0;
>>  volatile boolean v = false;
>>  public void writer() {
>>    x = 42;
>>    v = true;
>>  }
>>
>>  public void reader() {
>>    if (v == true) {
>>      //uses x - guaranteed to see 42.
>>    }
>>  }
>> }
>>
>> Why would v=true be seen by another thread ever? Just because there is
>> x access somewhere "nearby"/"same class"... what?
>
> No, the important thing is that v is volatile so therefore any writes that 
> happen before the write to v (such as x = 42) are guaranteed to be seen by 
> any thread when they read v. The test above shows that as long as v is 
> volatile the threads can still communicate values through other variables 
> such as x, as long as they respect the "happens-before" relationship with v.
>
>> I tested this and it doesn't work as advertised;
>
> The test below is wrong - v should be volatile as in the original code above, 
> not x, because the "happens-before" write vs read relationship is on v - 
> that's also why it works when you changed it to read x, because you're 
> restoring the "happens-before" relationship
>
>> package org.apache.pivot;
>>
>> public class Main
>> {
>>    public static void main( String[] args )
>>    {
>>        final Main m = new Main();
>>        Thread t1 = new Thread( new Runnable()
>>        {
>>
>>            @Override
>>            public void run()
>>            {
>>                try
>>                {
>>                    Thread.sleep( 50 );
>>                }
>>                catch( InterruptedException e )
>>                {
>>                    e.printStackTrace();  //To change body of catch
>> statement use File | Settings | File Templates.
>>                }
>>                m.writer();
>>            }
>>        } );
>>        Thread t2 = new Thread( new Runnable()
>>        {
>>            @Override
>>            public void run()
>>            {
>>                int i = 0;
>>                try
>>                {
>>                    while( true )
>>                    {
>>                        m.reader();
>>                        i++;
>>                    }
>>                }
>>                catch( InterruptedException e )
>>                {
>>                    System.out.println( "Works: " + i );
>>                }
>>            }
>>        } );
>>        t1.start();
>>        t2.start();
>>    }
>>
>>    private volatile int x = 0;
>>    private boolean v = false;
>>
>>    private void writer()
>>    {
>>        x = 42;
>>        v = true;
>>    }
>>
>>    private void reader()
>>        throws InterruptedException
>>    {
>>        if( v == true )
>>        {
>> //            if( x == 42 )
>>            throw new InterruptedException( "" + x );
>>        }
>>    }
>> }
>>
>> This code doesn't stop.
>> BUT if I add the "if( x == 42 )" then it does stop. WHY ON EARTH??
>>
>>
>>
>> I am getting more confused by the hours here... :-(
>>
>>
>> On Fri, Aug 26, 2011 at 12:45 PM, Stuart McCulloch <[email protected]> wrote:
>>> On 26 Aug 2011, at 05:13, Niclas Hedhman wrote:
>>>
>>>> On Fri, Aug 26, 2011 at 11:06 AM, Stuart McCulloch <[email protected]> 
>>>> wrote:
>>>>> On 26 Aug 2011, at 03:57, Niclas Hedhman wrote:
>>>>>
>>>>>> I think that is correct.
>>>>>> Assuming the 'next' is volatile, right?
>>>>>
>>>>> I don't believe 'next' has to be volatile, since the AtomicReference acts 
>>>>> as a memory barrier
>>>>
>>>> If not, the changed value in 'next' might not be visible to another
>>>> thread, just sitting in cache of a core/cpu.
>>>
>>> According to the AtomicReference javadoc:
>>>
>>>   
>>> http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/atomic/package-summary.html
>>>
>>>   "The memory effects for accesses and updates of atomics generally follow 
>>> the rules for volatiles:
>>>      * get has the memory effects of reading a volatile variable.
>>>      * set has the memory effects of writing (assigning) a volatile 
>>> variable.
>>>      * weakCompareAndSet atomically reads and conditionally writes a 
>>> variable, is ordered with respect to other memory operations on that 
>>> variable, but otherwise acts as an ordinary non-volatile memory operation.
>>>      * compareAndSet and all other read-and-update operations such as 
>>> getAndIncrement have the memory effects of both reading and writing 
>>> volatile variables."
>>>
>>> So any thread getting an instance from the pool makes at least a volatile 
>>> read via the atomic reference, and any thread returning an instance to the 
>>> pool makes at least a volatile write via the atomic reference. This sets up 
>>> a "happens-before" relationship, which will cause any pending changes in 
>>> the cache to be flushed to main memory:
>>>
>>>   http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
>>>   http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#volatile
>>>
>>> Or in other words you don't have to make every shared variable volatile 
>>> when doing inter-thread communication, you just need to have the right 
>>> "happens-before" relationship on at least one shared variable. (This is 
>>> also why double-checked locking works correctly in Java5+ whereas it didn't 
>>> in earlier JVMs).
>>>
>>> But if you want to be really, really sure then marking the 'next' field as 
>>> volatile won't cause problems (may affect performance, but probably not by 
>>> much)
>>>
>>>>
>>>> Cheers
>>>> --
>>>> Niclas Hedhman, Software Developer
>>>> http://www.qi4j.org - New Energy for Java
>>>>
>>>> I live here; http://tinyurl.com/3xugrbk
>>>> I work here; http://tinyurl.com/24svnvk
>>>> I relax here; http://tinyurl.com/2cgsug
>>>>
>>>> _______________________________________________
>>>> qi4j-dev mailing list
>>>> [email protected]
>>>> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>>>
>>>
>>> _______________________________________________
>>> qi4j-dev mailing list
>>> [email protected]
>>> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>>>
>>
>>
>>
>> --
>> Niclas Hedhman, Software Developer
>> http://www.qi4j.org - New Energy for Java
>>
>> I live here; http://tinyurl.com/3xugrbk
>> I work here; http://tinyurl.com/24svnvk
>> I relax here; http://tinyurl.com/2cgsug
>>
>> _______________________________________________
>> qi4j-dev mailing list
>> [email protected]
>> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>
>
> _______________________________________________
> qi4j-dev mailing list
> [email protected]
> http://lists.ops4j.org/mailman/listinfo/qi4j-dev
>



-- 
Niclas Hedhman, Software Developer
http://www.qi4j.org - New Energy for Java

I live here; http://tinyurl.com/3xugrbk
I work here; http://tinyurl.com/24svnvk
I relax here; http://tinyurl.com/2cgsug

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to