Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java When using synchronized do I get volatile functionality for free?

I read several posts about concurrency problems but I'm still unsure about something. Can I say that when using synchronized, I get volatile functionality for free, because when the lock on an object will be released, the next thread always reads the modified object. With volatile, the value of an object is immediately reflected to other threads. But when I use synchronized, there is no possibility to immediately reflect it due to the lock on the object. When the lock is released, only then another thread may access it. So I don't have to care about reflecting the value immediately to other threads. Do I understand this right?

[UPDATE]
Example prints always 1 2 3 4 5 6 7 8 9 without volatile.

package main;

public class Counter
{
    public static long count = 0;
}

public class UseCounter implements Runnable
{
    public void increment()
    {
        synchronized (this)
        {       
            Counter.count++;
            System.out.print(Counter.count + " ");
        }
    }

    @Override
    public void run()
    {
        increment();
        increment();
        increment();
    }
}

public class DataRace
{
    public static void main(String args[])
    {
        UseCounter c = new UseCounter();

        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);
        Thread t3 = new Thread(c);

        t1.start();
        t2.start();
        t3.start();
    }
}
like image 455
Bevor Avatar asked Oct 20 '22 09:10

Bevor


1 Answers

No, a volatile access is not implied by synchronized access according the the Java Memory Model (although on particular implementations, it may be, but you should not depend on that)

Java Language Specification 17.4.4 (on the Java Memory Model):

Synchronization actions induce the synchronized-with relation on actions, defined as follows:

  • An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where "subsequent" is defined according to the synchronization order).

  • A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).

volatile operates on a variable and synchronized operates on the monitor (the 'lock') of an object.

If one Thread A has just exited a synchronized block on object O, and another Thread B has just read a volatile variable (instance field) V on object O, then there is still not a synchronized-with relation between the two threads. There is no guarantee that Thread A will see any data modifications done by Thread B or vice versa, until Thread B also synchronized on object O, or until Thread A also accessed volatile field V on object O.

like image 126
Erwin Bolwidt Avatar answered Oct 23 '22 11:10

Erwin Bolwidt