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

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();
}
}

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.

Having a volatile variable isn't the same as synchronized access. When you mark a variable as volatile, Thread objects accessing the object will not keep a local cache and there will only ever be one "copy". If you combine the two (synchronized and volatile) then it will always be the updated version, and you won't have conflicting access of it.

Your code is guaranteed to print 1 2 3 4 5 6 7 8 9. The reason is that if you have a sequence such as
Thread t1 writes to Counter.count
Thread t1 unlocks object c
Thread t2 locks object c
Thread t2 reads Counter.count
then it is guaranteed that the read at step 4 sees the write at step 1.
This is not the same as volatile because it is not guaranteed that the write is reflected back to memory immediately, rather it is only guaranteed that the write in step 1 is visible to t2 at the end of step 3.

Related

If a simple write is done inside a synchronized block , then a read in another synchronized block is consistent?

The value written to a variable by one thread and other thread reading it in case both the operations are enclosed within synchronized blocks but both defined on different objects as below.
private Object o1 = new Object();
private Object o2 = new Object();
private int x = 0;
...
synchronized(o1){
x = 10;//write (simple atomic write) inside the synchronized block so value is flushed to main memory
}
...
synchronized(o2){
System.out.println(x);// read inside the synchronized block so read from main memory and not from thread cache.
}
Q1. Is it guaranteed that read is consistent with the latest value of x ?
Another case
private Object a = new Object();
private Object b = new Object();
private int p = 0;
...
synchronized(a){
p = p + 1;
}
....
synchronized(b){
System.out.println(p);
}
Q2. As the p = p+1 is not atomic hence we may have data inconsistencies in this case. But for the Q1. case as the write is simple and atomic an done in synchronized block hence in that case we have consistency.
Please help me if my understanding is correct.
Q1. Is it guaranteed that read is consistent with the latest value of x ?
No, because they are synchronized on different things.
There is a happens-before relationship between the end of a synchronized block and the start of a block synchronized on the same monitor.
There is no such relationship if the monitors are different.
You can find this in the language spec JLS 17.4.5 (emphasis mine):
It follows from the above definitions that:
An unlock on a monitor happens-before every subsequent lock on that monitor.
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
A call to start() on a thread happens-before any actions in the started thread.
All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
The default initialization of any object happens-before any other actions (other than default-writes) of a program.
Q2. As the p = p+1 is not atomic hence we may have data inconsistencies in this case. But for the Q1. case as the write is simple and atomic an done in synchronized block hence in that case we have consistency.
You don't have consistency. See answer to Q1.
The synchronized block, in addition to locking, ensures that the values that are read inside are relevant and taken from the main memory, and even before the block is released, all the changed data will be transferred to the main memory.

Quartz Job call synchronized method before completion of first one [duplicate]

I have some questions regarding the usage and significance of the synchronized keyword.
What is the significance of the synchronized keyword?
When should methods be synchronized?
What does it mean programmatically and logically?
The synchronized keyword is all about different threads reading and writing to the same variables, objects and resources. This is not a trivial topic in Java, but here is a quote from Sun:
synchronized methods enable a simple
strategy for preventing thread
interference and memory consistency
errors: if an object is visible to
more than one thread, all reads or
writes to that object's variables are
done through synchronized methods.
In a very, very small nutshell: When you have two threads that are reading and writing to the same 'resource', say a variable named foo, you need to ensure that these threads access the variable in an atomic way. Without the synchronized keyword, your thread 1 may not see the change thread 2 made to foo, or worse, it may only be half changed. This would not be what you logically expect.
Again, this is a non-trivial topic in Java. To learn more, explore topics here on SO and the Interwebs about:
Concurrency
Java Memory Model
Keep exploring these topics until the name "Brian Goetz" becomes permanently associated with the term "concurrency" in your brain.
Well, I think we had enough of theoretical explanations, so consider this code
public class SOP {
public static void print(String s) {
System.out.println(s+"\n");
}
}
public class TestThread extends Thread {
String name;
TheDemo theDemo;
public TestThread(String name,TheDemo theDemo) {
this.theDemo = theDemo;
this.name = name;
start();
}
#Override
public void run() {
theDemo.test(name);
}
}
public class TheDemo {
public synchronized void test(String name) {
for(int i=0;i<10;i++) {
SOP.print(name + " :: "+i);
try{
Thread.sleep(500);
} catch (Exception e) {
SOP.print(e.getMessage());
}
}
}
public static void main(String[] args) {
TheDemo theDemo = new TheDemo();
new TestThread("THREAD 1",theDemo);
new TestThread("THREAD 2",theDemo);
new TestThread("THREAD 3",theDemo);
}
}
Note: synchronized blocks the next thread's call to method test() as long as the previous thread's execution is not finished. Threads can access this method one at a time. Without synchronized all threads can access this method simultaneously.
When a thread calls the synchronized method 'test' of the object (here object is an instance of 'TheDemo' class) it acquires the lock of that object, any new thread cannot call ANY synchronized method of the same object as long as previous thread which had acquired the lock does not release the lock.
Similar thing happens when any static synchronized method of the class is called. The thread acquires the lock associated with the class(in this case any non static synchronized method of an instance of that class can be called by any thread because that object level lock is still available). Any other thread will not be able to call any static synchronized method of the class as long as the class level lock is not released by the thread which currently holds the lock.
Output with synchronised
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9
Output without synchronized
THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
The synchronized keyword prevents concurrent access to a block of code or object by multiple threads. All the methods of Hashtable are synchronized, so only one thread can execute any of them at a time.
When using non-synchronized constructs like HashMap, you must build thread-safety features in your code to prevent consistency errors.
synchronized means that in a multi threaded environment, an object having synchronized method(s)/block(s) does not let two threads to access the synchronized method(s)/block(s) of code at the same time. This means that one thread can't read while another thread updates it.
The second thread will instead wait until the first thread completes its execution. The overhead is speed, but the advantage is guaranteed consistency of data.
If your application is single threaded though, synchronized blocks does not provide benefits.
The synchronized keyword causes a thread to obtain a lock when entering the method, so that only one thread can execute the method at the same time (for the given object instance, unless it is a static method).
This is frequently called making the class thread-safe, but I would say this is a euphemism. While it is true that synchronization protects the internal state of the Vector from getting corrupted, this does not usually help the user of Vector much.
Consider this:
if (vector.isEmpty()){
vector.add(data);
}
Even though the methods involved are synchronized, because they are being locked and unlocked individually, two unfortunately timed threads can create a vector with two elements.
So in effect, you have to synchronize in your application code as well.
Because method-level synchronization is a) expensive when you don't need it and b) insufficient when you need synchronization, there are now un-synchronized replacements (ArrayList in the case of Vector).
More recently, the concurrency package has been released, with a number of clever utilities that take care of multi-threading issues.
Overview
Synchronized keyword in Java has to do with thread-safety, that is, when multiple threads read or write the same variable.
This can happen directly (by accessing the same variable) or indirectly (by using a class that uses another class that accesses the same variable).
The synchronized keyword is used to define a block of code where multiple threads can access the same variable in a safe way.
Deeper
Syntax-wise the synchronized keyword takes an Object as it's parameter (called a lock object), which is then followed by a { block of code }.
When execution encounters this keyword, the current thread tries to "lock/acquire/own" (take your pick) the lock object and execute the associated block of code after the lock has been acquired.
Any writes to variables inside the synchronized code block are guaranteed to be visible to every other thread that similarly executes code inside a synchronized code block using the same lock object.
Only one thread at a time can hold the lock, during which time all other threads trying to acquire the same lock object will wait (pause their execution). The lock will be released when execution exits the synchronized code block.
Synchronized methods:
Adding synchronized keyword to a method definition is equal to the entire method body being wrapped in a synchronized code block with the lock object being this (for instance methods) and ClassInQuestion.getClass() (for class methods).
- Instance method is a method which does not have static keyword.
- Class method is a method which has static keyword.
Technical
Without synchronization, it is not guaranteed in which order the reads and writes happen, possibly leaving the variable with garbage.
(For example a variable could end up with half of the bits written by one thread and half of the bits written by another thread, leaving the variable in a state that neither of the threads tried to write, but a combined mess of both.)
It is not enough to complete a write operation in a thread before (wall-clock time) another thread reads it, because hardware could have cached the value of the variable, and the reading thread would see the cached value instead of what was written to it.
Conclusion
Thus in Java's case, you have to follow the Java Memory Model to ensure that threading errors do not happen.
In other words: Use synchronization, atomic operations or classes that use them for you under the hoods.
Sources
http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java® Language Specification, 2015-02-13
Think of it as a kind of turnstile like you might find at a football ground. There are parallel steams of people wanting to get in but at the turnstile they are 'synchronised'. Only one person at a time can get through. All those wanting to get through will do, but they may have to wait until they can go through.
What is the synchronized keyword?
Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.
Synchronized blocks or methods prevents thread interference and make sure that data is consistent. At any point of time, only one thread can access a synchronized block or method (critical section) by acquiring a lock. Other thread(s) will wait for release of lock to access critical section.
When are methods synchronized?
Methods are synchronized when you add synchronized to method definition or declaration. You can also synchronize a particular block of code with-in a method.
What does it mean pro grammatically and logically?
It means that only one thread can access critical section by acquiring a lock. Unless this thread release this lock, all other thread(s) will have to wait to acquire a lock. They don't have access to enter critical section with out acquiring lock.
This can't be done with a magic. It's programmer responsibility to identify critical section(s) in application and guard it accordingly. Java provides a framework to guard your application, but where and what all sections to be guarded is the responsibility of programmer.
More details from java documentation page
Intrinsic Locks and Synchronization:
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.
A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.
Making methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave.
When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object.
This guarantees that changes to the state of the object are visible to all threads.
Look for other alternatives to synchronization in :
Avoid synchronized(this) in Java?
Synchronized normal method equivalent to
Synchronized statement (use this)
class A {
public synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(this) {
// all function code
}
}
}
Synchronized static method equivalent to Synchronized statement (use class)
class A {
public static synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(A.class) {
// all function code
}
}
}
Synchronized statement (using variable)
class A {
private Object lock1 = new Object();
public void methodA() {
synchronized(lock1 ) {
// all function code
}
}
}
For synchronized, we have both Synchronized Methods and Synchronized Statements. However, Synchronized Methods is similar to Synchronized Statements so we just need to understand Synchronized Statements.
=> Basically, we will have
synchronized(object or class) { // object/class use to provides the intrinsic lock
// code
}
Here is 2 think that help understanding synchronized
Every object/class have an intrinsic lock associated with it.
When a thread invokes a synchronized statement, it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns. As long as a thread owns an intrinsic lock, NO other thread can acquire the SAME lock => thread safe.
=>
When a thread A invokes synchronized(this){// code 1} => all the block code (inside class) where have synchronized(this) and all synchronized normal method (inside class) is locked because SAME lock. It will execute after thread A unlock ("// code 1" finished).
This behavior is similar to synchronized(a variable){// code 1} or synchronized(class).
SAME LOCK => lock (not depend on which method? or which statements?)
Use synchronized method or synchronized statements?
I prefer synchronized statements because it is more extendable. Example, in future, you only need synchronized a part of method. Example, you have 2 synchronized method and it don't have any relevant to each other, however when a thread run a method, it will block the other method (it can prevent by use synchronized(a variable)).
However, apply synchronized method is simple and the code look simple. For some class, there only 1 synchronized method, or all synchronized methods in the class in relevant to each other => we can use synchronized method to make code shorter and easy to understand
Note
(it not relevant to much to synchronized, it is the different between object and class or none-static and static).
When you use synchronized or normal method or synchronized(this) or synchronized(non-static variable) it will synchronized base on each object instance.
When you use synchronized or static method or synchronized(class) or synchronized(static variable) it will synchronized base on class
Reference
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Hope it help
Here is an explanation from The Java Tutorials.
Consider the following code:
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
if count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
To my understanding synchronized basically means that the compiler write a monitor.enter and monitor.exit around your method. As such it may be thread safe depending on how it is used (what I mean is you can write an object with synchronized methods that isn't threadsafe depending on what your class does).
What the other answers are missing is one important aspect: memory barriers. Thread synchronization basically consists of two parts: serialization and visibility. I advise everyone to google for "jvm memory barrier", as it is a non-trivial and extremely important topic (if you modify shared data accessed by multiple threads). Having done that, I advise looking at java.util.concurrent package's classes that help to avoid using explicit synchronization, which in turn helps keeping programs simple and efficient, maybe even preventing deadlocks.
One such example is ConcurrentLinkedDeque. Together with the command pattern it allows to create highly efficient worker threads by stuffing the commands into the concurrent queue -- no explicit synchronization needed, no deadlocks possible, no explicit sleep() necessary, just poll the queue by calling take().
In short: "memory synchronization" happens implicitly when you start a thread, a thread ends, you read a volatile variable, you unlock a monitor (leave a synchronized block/function) etc. This "synchronization" affects (in a sense "flushes") all writes done before that particular action. In the case of the aforementioned ConcurrentLinkedDeque, the documentation "says":
Memory consistency effects: As with other concurrent collections,
actions in a thread prior to placing an object into a
ConcurrentLinkedDeque happen-before actions subsequent to the access
or removal of that element from the ConcurrentLinkedDeque in another
thread.
This implicit behavior is a somewhat pernicious aspect because most Java programmers without much experience will just take a lot as given because of it. And then suddenly stumble over this thread after Java isn't doing what it is "supposed" to do in production where there is a different work load -- and it's pretty hard to test concurrency issues.
Synchronized simply means that multiple threads if associated with single object can prevent dirty read and write if synchronized block is used on particular object. To give you more clarity , lets take an example :
class MyRunnable implements Runnable {
int var = 10;
#Override
public void run() {
call();
}
public void call() {
synchronized (this) {
for (int i = 0; i < 4; i++) {
var++;
System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
}
}
}
}
public class MutlipleThreadsRunnable {
public static void main(String[] args) {
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
Thread t1 = new Thread(runnable1);
t1.setName("Thread -1");
Thread t2 = new Thread(runnable2);
t2.setName("Thread -2");
Thread t3 = new Thread(runnable1);
t3.setName("Thread -3");
t1.start();
t2.start();
t3.start();
}
}
We've created two MyRunnable class objects , runnable1 being shared with thread 1 and thread 3 & runnable2 being shared with thread 2 only.
Now when t1 and t3 starts without synchronized being used , PFB output which suggest that both threads 1 and 3 simultaneously affecting var value where for thread 2 , var has its own memory.
Without Synchronized keyword
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -2 var value 12
Current Thread Thread -2 var value 13
Current Thread Thread -2 var value 14
Current Thread Thread -1 var value 12
Current Thread Thread -3 var value 13
Current Thread Thread -3 var value 15
Current Thread Thread -1 var value 14
Current Thread Thread -1 var value 17
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 18
Using Synchronzied, thread 3 waiting for thread 1 to complete in all scenarios. There are two locks acquired , one on runnable1 shared by thread 1 and thread 3 and another on runnable2 shared by thread 2 only.
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
In java to prevent multiple threads manipulating a shared variable we use synchronized keyword. Lets understand it with help of the following example:
In the example I have defined two threads and named them increment and decrement. Increment thread increases the value of shared variable (counter) by the same amount the decrement thread decreases it i.e 5000 times it is increased (which result in 5000 + 0 = 5000) and 5000 times we decrease (which result in 5000 - 5000 = 0).
Program without synchronized keyword:
class SynchronizationDemo {
public static void main(String[] args){
Buffer buffer = new Buffer();
MyThread incThread = new MyThread(buffer, "increment");
MyThread decThread = new MyThread(buffer, "decrement");
incThread.start();
decThread.start();
try {
incThread.join();
decThread.join();
}catch(InterruptedException e){ }
System.out.println("Final counter: "+buffer.getCounter());
}
}
class Buffer {
private int counter = 0;
public void inc() { counter++; }
public void dec() { counter--; }
public int getCounter() { return counter; }
}
class MyThread extends Thread {
private String name;
private Buffer buffer;
public MyThread (Buffer aBuffer, String aName) {
buffer = aBuffer;
name = aName;
}
public void run(){
for (int i = 0; i <= 5000; i++){
if (name.equals("increment"))
buffer.inc();
else
buffer.dec();
}
}
}
If we run the above program we expect value of buffer to be same since incrementing and decrementing the buffer by same amount would result in initial value we started with right ?. Lets see the output:
As you can see no matter how many times we run the program we get a different result reason being each thread manipulated the counter at the same time. If we could manage to let the one thread to first increment the shared variable and then second to decrement it or vice versa we will then get the right result that is exactly what can be done with synchronized keyword by just adding synchronized keyword before the inc and dec methods of Buffer like this:
Program with synchronized keyword:
// rest of the code
class Buffer {
private int counter = 0;
// added synchronized keyword to let only one thread
// be it inc or dec thread to manipulate data at a time
public synchronized void inc() { counter++; }
public synchronized void dec() { counter--; }
public int getCounter() { return counter; }
}
// rest of the code
and the output:
no matter how many times we run it we get the same output as 0
Java synchronized
volatile[About] => synchronized
synchronized block in Java is a monitor in multithreading. synchronized block with the same object/class can be executed by only single thread, all others are waiting. It can help with race condition[About] situation.
Java 5 extended synchronized by supporting happens-before[About]
An unlock (synchronized block or method exit) of a monitor happens-before every subsequent lock (synchronized block or method entry) of that same monitor.
The next step is java.util.concurrent
synchronized simple means no two threads can access the block/method simultaneously. When we say any block/method of a class is synchronized it means only one thread can access them at a time. Internally the thread which tries to access it first take a lock on that object and as long as this lock is not available no other thread can access any of the synchronized methods/blocks of that instance of the class.
Note another thread can access a method of the same object which is not defined to be synchronized. A thread can release the lock by calling
Object.wait()
synchronized is a keyword in Java which is used to make happens before relationship in multithreading environment to avoid memory inconsistency and thread interference error.

Guarding the initialization of a non-volatile field with a lock?

For educational purposes I'm writing a simple version of AtomicLong, where an internal variable is guarded by ReentrantReadWriteLock.
Here is a simplified example:
public class PlainSimpleAtomicLong {
private long value;
private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public PlainSimpleAtomicLong(long initialValue) {
this.value = initialValue;
}
public long get() {
long result;
rwLock.readLock().lock();
result = value;
rwLock.readLock().unlock();
return result;
}
// incrementAndGet, decrementAndGet, etc. are guarded by rwLock.writeLock()
}
My question: since "value" is non-volatile, is it possible for other threads to observe incorrect initial value via PlainSimpleAtomicLong.get()?
E.g. thread T1 creates L = new PlainSimpleAtomicLong(42) and shares reference with a thread T2. Is T2 guaranteed to observe L.get() as 42?
If not, would wrapping this.value = initialValue; into a write lock/unlock make a difference?
Chapter 17 reasons about concurrent code in terms of happens before relationships. In your example, if you take two random threads then there is no happens-before relationship between this.value = initialValue; and result = value;.
So if you have something like:
T1.start();
T2.start();
...
T1: L = new PlainSimpleAtomicLong(42);
T2: long value = L.get();
The only happens-before (hb) relationships you have (apart from program order in each thread) is: 1 & 2 hb 3,4,5.
But 4 and 5 are not ordered. If however T1 called L.get() before T2 called L.get() (from a wall clock perspective) then you would have a hb relationship between unlock() in T1 and lock() in T2.
As already commented, I don't think your proposed code could break on any combination of JVM/hardware but it could break on a theoretical implementation of the JMM.
As for your suggestion to wrap the constructor in a lock/unlock, I don't think it would be enough because, in theory at least, T1 could release a valid reference (non null) to L before running the body of the constructor. So the risk would be that T2 could acquire the lock before T1 has acquired it in the constructor. There again, this is an interleaving that is probably impossible on current JVMs/hardware.
So to conclude, if you want theoretical thread safety, I don't think you can do without a volatile long value, which is how AtomicLong is implemented. volatile would guarantee that the field is initialised before the object is published. Note finally that the issues I mention here are not due to your object being unsafe (see #BrettOkken answer) but are based on a scenario where the object is not safely published across threads.
Assuming that you do not allow a reference to the instance to escape your constructor (your example looks fine), then a second thread can never see the object with any value of "value" other than what it was constructed with because all accesses are protected by a monitor (the read write lock) which was final in the constructor.
https://www.ibm.com/developerworks/library/j-jtp0618/
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
I think that for initial values , than both threads would see the same values (since they can have the object only after the constructor is finished).
But
If you change the value in 1 thread , then other thread may not see the same value if you don't use volatile
If you want to implement set, wrapping set with lock/unlock will not solve the problem - this is good when need atomic operation (like increment).
I
It doesn't mean that it would work the way you want since you don't control the context switch. For example if 2 threads call set, with values 4 & 8 , since you don't know when the context switch occurs , you don't know who will gain the lock first.

Does synchronized guarantee a thread will see the latest value of a non-volatile variable being modified by another thread?

Here is a simple example:
private long counter = 0;
// note this method is NOT synchronized
// this will be called by thread A
public void increment() { counter++; }
// note this method IS synchronized
// this will be called by thread B
public synchronized long value() { return counter; }
So I just want to get a good value for counter, not a stuck value in the cpu cache because the variable is non-volatile. The goal is to NOT make counter volatile so it does NOT impact thread A doing the increments, but only thread B, which I don't care, when it reads the variable.
Just for the record, I plan to read the value of counter from thread B when thread A has already finished anyways...
No, the synchronized block in thread B does not ensure that it will read the actual current value of counter. You would need synchronized blocks in both threads to do that. From a practical perspective, your code ensures that the processor running thread B invalidates its cache and reads the value of counter from main memory, but it does not ensure that the processor running thread A flushes its current value to main memory, so the value in main memory may be stale.
Since using a volatile variable is cheaper than synchronized blocks in both threads, making counter volatile is likely the correct solution. This is what volatile variables are for.
Edit: if thread A is going to complete before thread B reads the final value, you could enclose the entire execution of thread A in a single synchronized block or have thread B join thread A before reading the counter, ensuring that thread A completes before the counter is read. That would result in one cache flush at the end of Thread A's execution, which would have negligible impact on performance.
long assignment is not guaranteed to be atomic, so not only could B read a stale value, it could also read a half written value.
For proper visibility you need to make counter volatile. Note that even then, calling increment n times from several threads may not increment counter by n.
You could use an AtomicLong to simply since your problem.
No, synchornized only guarantees visibility of changes that were made within synchronized blocks of the same lock:
synchornized(this) {
counter++;
}
or before them (as defined by transitive nature of happens-before relationship):
// Thread A
counter++
synchronized (this) {
finished = true;
}
// Thread B
synchonized (this) {
if (finished) {
// you can read counter here
}
}
Note, however, that counter is guaranteed to be visibile if you read it after you positively determined that Thread A has finished (for example, using join()):
threadA.join();
// you can read counter here
No.There is no guarantee that Thread B will gives latest value always.Since increment() is non-synchronized method and value() is synchronized method.
Since
While a thread is inside a synchronized method of an object, all other threads that wish to execute this synchronized method or any other synchronized method of the object will have to wait.
This restriction does not apply to the thread that already has the lock and is executing a synchronized method of the object. Such a method can invoke other synchronized methods of the object without being blocked. The non-synchronized methods of the object can of course be called at any time by any thread.

Does deadlock happen per method or per class?

Immagine that I have Class First with several synchronised methods. When a thread locks the class First, does it lock per method or per class? For example does deadlock happen for the following code?
public class DeadLockQuestion {
public static class First{
public synchronized void a(){
}
public synchronized void b(){
}
public synchronized void c(){
}
public synchronized void d(){
}
public synchronized void e(){
}
}
public static void main(String... args){
First f = new First();
//This code is run in Thread 1
f.a();
// End
//This code is run in Thread 2 simultanously
f.b();
//End
// We have also Threads 3 & 4 & 5 that invoke c,d and e simultanously
}
}
You have got two locks in Java. One is Object lock. and the other is Class Lock.
The object lock locks access to synchronized non-static functions only. and Class lock locks on synchronized static functions only.
For you, its an object lock on object f. So all the synchronized non-static functions are locked for object f.
Since all the Threads are using the same object f, Only one Thread will be able to access your non-static functions a(), b(),... at a time.
Read more here
does deadlock happen for the following code?
No, it won't happen in your case. Because While one Thread is holding the lock, Other threads can't get inside your synchronized function.DeadLock happens due to resources.
You have only one resource thats Object f. There's no point of a dead-lock here because the class First doesn't lock another object and no cyclic lock can happen. Deadlock requires a cyclic lock!
Some Info:
Synchronization in java guarantees that no two threads can execute a
synchronized method which requires same lock simultaneously or
concurrently.
synchronized keyword can be used only with methods and code blocks.
These methods or blocks can be static or non-static both.
When ever a thread enters into java synchronized method or block it
acquires a lock and whenever it leaves java synchronized method or
block it releases the lock. Lock is released even if thread leaves
synchronized method after completion or due to any Error or
Exception.
It’s possible that both static synchronized and non static
synchronized method can run simultaneously or concurrently because
they lock on different object.
Useful Source Here, and here
Deadlock happens to threads, not to methods or classes.
The deadlocked threads also hold locks, but in this case it is impossible to tell which locks because you do not demonstrate an actual deadlock scenario (if two threads call synchronized methods of f one goes through and the other waits; deadlock requires at least two locks).
To lock each method independently use a synchronized block within each method and lock on a different object.
If you have an appropriate (and it should be final to prevent potential problems) object already within the class you can use that. If not create a private final Object aLock = new Object(); and then lock on that, for example:
private final Object aLock = new Object();
public void a() {
synchronized(aLock) {
// Do stuff that needs the lock
}
// do stuff that doesn't need the lock
}
Always hold the lock for as long as you need it, but no longer.
When a() is a synchronized method, f.a() literally means:
synchronized(f){
f.a();
}
So in this case a lock would happen for object monitor f. In your case you would require a second object to create a deadlock, I don't think it's possible to create a deadlock with a single object monitor. A typical deadlock pattern is when an order of lock acquisition is not being maintained, i.e. when this happens in two different threads:
synchronized(a){
synchronized(b){
...
}
}
// and
synchronized(b){
synchronized(a){
...
}
}
Firstly, Deadlock occurs with threads and not classes or methods.
Deadlock occurs when there is a cyclic dependency of locks.
Thread A ---> locks L1 ---> tries to lock L2
Thread B ----> locks L2 ------> tries to lock L1
Image source: FusionReactor deadlock plugin

Categories

Resources