public class IntermediateMessage {
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock read = readWriteLock.readLock();
private final Lock write = readWriteLock.writeLock();
private volatile double ratio;
public IntermediateMessage(){
this.ratio=1.0d;
}
public IntermediateMessage(double ratio){
this.ratio = ratio;
}
public double getRatio(){
read.lock();
try{
return this.ratio;
}
finally{
read.unlock();
}
}
public void setRatio(double ratio){
write.lock();
try{
this.ratio = ratio;
}
finally{
write.unlock();
}
}
}
I have this object. I have an instance of this object in my application and one thread is writing to the ratio variable while the other threads are reading the ratio. Is this correct way to protect the ratio variable? Do I need to declare ratio as volatile?
Do you need locking at all? Most likely not, according to the limited requirements you've described. But read this to be sure...
You have just one thread writing.
This means that the variable value can never be "out of date" due to competing writers "clobbering" one another (no possible race condition). So no locking is required to give integrity when considering the individual variable in isolation.
You have not mentioned whether some form of atomic, consistent modification of multiple variables is required. I assume it isn't.
IF ratio must always be consistent with other variables (e.g. in other objects) - i.e. if a set of variables must change in synchrony as a group with no one reading just part of the changes - then locking is required to give atomic consistency to the set of variables. Then consistent variables must be modified together within in a single locked region and readers must obtain the same lock before reading any of these set of variables (waiting in a blocked state, if necessary).
IF ratio can be changed at any time as a lone variable and need not be kept consistent with other variables, then no locking is required give atomic consistency to a set of variables.
Do you need the volatile modifier? Well, yes!
You have multiple threads reading.
The variable can change at any moment, including an instant before it's about to be read.
The volatile modifier is used in multi-threaded apps to guarantee that the value read by "readers" always matches the value written by "writers".
You are doing some overkill on the synchronization that is going to cause some inefficiency.
The java keyword "volatile" means that variable won't be cached, and that it will have synchronized access for multiple threads.
So you are locking a variable that is already by default synchronized.
So you should either remove the volatile keyword, or remove the reentrant locks. Probably the volatile as you will be more efficient with multiple reads the way you are currently synchronizing.
For reading/writing a primitive value, volatile alone is sufficient.
Provided two threads are trying to read and write on the same object and you want the data integrity to be mantained. Just make your getter and setter synchronized. When a method is synchonized, only one thread will be able to call a synchronize method. While one thread is executing one of the synchronized method, no other thread will be able to call any of the synchronized method. So in your case if you have your get & set method synchronized, you can be sure if a thread is reading/writing no other thread can do the reading/writing.
Hope it helps!
Make ratio final and it will be thread safe.
Related
I have a requirement of locking several objects in one method in my java class. For an example look at the following class:
public class CounterMultiplexer {
private int counter =0;
private int multiPlexer =5;
private Object mutex = new Object();
public void calculate(){
synchronized(mutex){
counter ++;
multiPlexer = multiPlexer*counter;
}
}
public int getCounter(){
return counter;
}
public int getMux(){
return multiPlexer;
}
}
In the above code, I have two resources that could access by a more than one thread. Those two resources are counter and the multiPlexer properties. As you can see in the above code I have locked both the resources using a mutex.
Is this way of locking is correct? Do I need to use nested Synchronized statements to lock both resources inside the calculate method?
So you've got the idea of mutex (and atomicity) correct. However there's an additional wrinkle in the Java memory model which is visibility that you have to take into consideration.
Basically, both reads and writes must be synchronized, or the read is not guaranteed to see the write. For your getters, it would be very easy for the JIT to hoist those values into a register and never re-read them, meaning the value written would never be seen. This is called a data race because the order of the write and the read cannot be guaranteed.
To break the data race, you have to use memory ordering semantics. This boils down to synchronizing both the reads and the writes. And you have to do this every time you need to use synchronization anywhere, not just in the specific case you have above.
You could use almost any method (like AtomicInteger) but probably the easiest is either to re-use the mutex you already have, or to make the two primitive values volatile. Either works, but you must use at least one.
public class CounterMultiplexer {
private int counter =0;
private int multiPlexer =5;
private Object mutex = new Object();
public void claculate(){
synchronized(mutex){
counter ++;
multiPlexer = multiPlexer*counter;
}
}
public int getCounter(){
synchronized(mutex){
return counter;
}
}
public int getMux(){
synchronized(mutex){
return multiPlexer;
}
}
}
So to get into this more, we have to read the spec. You can also get Brian Goetz's Java Concurrency in Practice which I highly recommend because he covers this sort of thing in detail and with simple examples that make it very clear that you must syncrhonize on both reads and writes, always.
The relevant section of the spec is Chapter 17, and in particular section 17.4 Memory Model.
Just to quote the relevant parts:
The Java programming language memory model works by examining each read in an execution trace and checking that the write observed by that read is valid according to certain rules.
That bit is important. Each read is checked. The model doesn't work by checking the writes alone and then assuming the reads can see the write.
Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.
The happens-before is what allows reads to see a write. Without it, the JVM is free to optimize your program in ways that might preclude seeing the write (like hoisting a value into a register).
The happens-before relation defines when data races take place.
A set of synchronization edges, S, is sufficient if it is the minimal set such that the transitive closure of S with the program order determines all of the happens-before edges in the execution. This set is unique.
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.
So happens-before defines when a data race does (or does not) take place. How volatile works I think is obvious from the description above. For a monitor (your mutex), it's important to note that happens-before is established by a unlock followed by a later lock, so to establish happens-before for the read, you do need to lock the monitor again just before the read.
We say that a read r of a variable v is allowed to observe a write w to v if, in the happens-before partial order of the execution trace:
r is not ordered before w (i.e., it is not the case that hb(r, w)), and
there is no intervening write w' to v (i.e. no write w' to v such that hb(w, w') and hb(w', r)).
Informally, a read r is allowed to see the result of a write w if there is no happens-before ordering to prevent that read.
"Allowed to observe" means the read actually will see the write. So happens-before is what we need to see the write, and either the lock (mutex in your program) or volatile will work.
There's lots more (other things cause happens-before) and there's the API too with classes in java.utli.concurrent that will also cause memory ordering (and visibility) semantics. But there's the gory details on your program.
No you don't need to use nested synchronized statements to lock both resource inside the calculate method. But you need to add synchronized clause in get methods also, synchronization is needed for both reading/writing into the resource.
public int getCounter(){
synchronized(mutex){
return counter;
}
}
public int getMux(){
synchronized(mutex){
return multiPlexer;
}
}
It is fine (better even) to use just a single mutex to protect both fields. The monitor object has nothing to do really with the fields or the object that holds them. In fact, it is good practice to use dedicated lock objects (instead of say this). You just have to make sure that all access to these fields end up using the same monitor.
However, it is not enough to wrap the setter in a synchronized block, all access to the (non-volatile) variables (including the getters) must be behind the same monitor.
Since the counter and the multiPlexer are locked simultaneously, they can be considered as a single resource. Moreover, the whole instance of the class CounterMultiplexer can be thought of as a single resource. In Java, considering an instance as a single resource is a most widespread approach. For this case, special synchronozed methods were introduced:
public synchronized void claculate(){
counter ++;
multiPlexer = multiPlexer*counter;
}
public synchronized int getCounter(){
return counter;
}
public synchronized int getMux(){
return multiPlexer;
}
The mutex variable is not needed anymore.
An alternative way to approach this kind of problem is to have all your member variables be final and for the calculate method to return a new instance of CounterMultiplexer. This guarantees that any instance of CounterMultiplexer is always in a consistent state. Depending on how you use this class, this approach would likely require synchronization outside of this class.
Synchronizing within the getters still allows for another thread to read one of the two member variables from before the change and one from after.
I want to track getVariableAndLogAccess(RequestInfo requestInfo) using the code below. Will it be thread safe if only these two methods access variable?
What is the standard way to make it thread safe?
public class MyAccessLog(){
private int recordIndex = 0;
private int variableWithAccessTracking = 42;
private final Map<Integer, RequestInfo> requestsLog = new HashMap<>();
public int getVariableAndLogAccess(RequestInfo requestInfo){
Integer myID = recordIndex++;
int variableValue = variableWithAccessTracking;
requestInfo.saveValue(variableValue);
requestLog.put(myID, requestInfo);
return variableValue;
}
public void setValueAndLog(RequestInfo requestInfo, int newValue){
Integer myID = recordIndex++;
variableWithAccessTracking = variableValue;
requestInfo.saveValue(variableValue);
requestLog.put(myID, requestInfo);
}
/*other methods*/
}
Will it be thread safe if only these two methods access variable?
No.
For instance, if two threads call setValueAndLog, they might end up with the same myID value.
What is the standard way to make it thread safe?
You should either replace your int with an AtomicInteger, use a lock, or a syncrhonized block to prevent concurrent modifications.
As a rule of thumb, using an atomic variable such as the previously mentioned AtomicInteger is better than using locks since locks involve the operating system. Calling the operating system is like bringing in the lawyers - both are best avoided for things you can solve yourself.
Note that if you use locks or synchronized blocks, both the setter and getter need to use the same lock. Otherwise the getter could be accessed while the setter is still updating the variable, leading to concurrency errors.
Will it be thread safe if only these two methods access variable?
Nope.
Intuitively, there are two reasons:
An increment consists of a read followed by a write. The JLS does not guarantee that the two will be performed as an atomic operation. And indeed, neither to Java implementations do that.
Modern multi-core systems implement memory access with fast local memory caches and slower main memory. This means that one thread is not guaranteed to see the results of another thread's memory writes ... unless there are appropriate "memory barrier" instructions to force main-memory writes / reads.
Java will only insert these instructions if the memory model says it is necessary. (Because ... they slow the code down!)
Technically, the JLS has a whole chapter describing the Java Memory Model, and it provides a set of rules that allow you to reason about whether memory is being used correctly. For the higher level stuff, you can reason based on the guarantees provided by AtomicInteger, etcetera.
What is the standard way to make it thread safe?
In this case, you could use either an AtomicInteger instance, or you could synchronize using a primitive object locking (i.e the synchronized keyword) or a Lock object.
#Malt is right. Your code is not even close to be thread safe.
You can use AtomicInteger for your counter, but LongAdder would be more suitable for your case, as it is optimized for cases where you need counting things and read the result of your counting less often then you update it. LongAdder also has the same thread safety assurance of AtomicInteger
From java doc on LongAdder:
This class is usually preferable to AtomicLong when multiple threads update a common sum that is used for purposes such as collecting statistics, not for fine-grained synchronization control. Under low update contention, the two classes have similar characteristics. But under high contention, expected throughput of this class is significantly higher, at the expense of higher space consumption.
This is a common approach to log in a thread safe way:
For counter use AtomicInteger counter with counter.addAndGet(1) method.
Add data using public synchronized void putRecord(Data data){ /**/}
If you only use recordIndex as a handler for the record you can replace a map with a synchronized list: List list = Collections.synchronizedList(new LinkedList());
I am trying to wrap my head around thread safety in java (or in general). I have this class (which I hope complies with the definition of a POJO) which also needs to be compatible with JPA providers:
public class SomeClass {
private Object timestampLock = new Object();
// are "volatile"s necessary?
private volatile java.sql.Timestamp timestamp;
private volatile String timestampTimeZoneName;
private volatile BigDecimal someValue;
public ZonedDateTime getTimestamp() {
// is synchronisation necessary here? is this the correct usage?
synchronized (timestampLock) {
return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of(timestampTimeZoneName));
}
}
public void setTimestamp(ZonedDateTime dateTime) {
// is this the correct usage?
synchronized (timestampLock) {
this.timestamp = java.sql.Timestamp.from(dateTime.toInstant());
this.timestampTimeZoneName = dateTime.getZone().getId();
}
}
// is synchronisation required?
public BigDecimal getSomeValue() {
return someValue;
}
// is synchronisation required?
public void setSomeValue(BigDecimal val) {
someValue = val;
}
}
As stated in the commented rows in the code, is it necessary to define timestamp and timestampTimeZoneName as volatile and are the synchronized blocks used as they should be? Or should I use only the synchronized blocks and not define timestamp and timestampTimeZoneName as volatile? A timestampTimeZoneName of a timestamp should not be erroneously matched with another timestamp's.
This link says
Reads and writes are atomic for all variables declared volatile
(including long and double variables)
Should I understand that accesses to someValue in this code through the setter/getter are thread safe thanks to volatile definitions? If so, is there a better (I do not know what "better" might mean here) way to accomplish this?
To determine if you need synchronized, try to imagine a place where you can have a context switch that would break your code.
In this case, if the context switch happens where I put the comment, then in getTimestamp() you're going to be reading different values from each timestamp type.
Also, although assignments are atomic, this expression java.sql.Timestamp.from(dateTime.toInstant()); certainly isn't, so you can get a context switch inbetween dateTime.toInstant() and the call to from. In short you definitely need the synchronized blocks.
synchronized (timestampLock) {
this.timestamp = java.sql.Timestamp.from(dateTime.toInstant());
//CONTEXT SWITCH HERE
this.timestampTimeZoneName = dateTime.getZone().getId();
}
synchronized (timestampLock) {
return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of(timestampTimeZoneName));
}
In terms of volatile, I'm pretty sure they're required. You have to guarantee that each thread definitely is getting the most updated version of a variable.
This is the contract of volatile. And although it may be covered by the synchronized block, and volatile not actually necessary here, it's good to write anyway. If the synchronized block does the job of volatile already, the VM won't do the guarantee twice. This means volatile won't cost you any more, and it's a very good flashing light that says to the programmer: "I'M USED IN MULTIPLE THREADS".
For someValue: If there's no synchronized block here, then volatile is definitely necessary. If you call a set in one thread, the other thread has no queue that tells it that may have been updated outside of this thread. So it may use an old and cached value. The JIT can do a lot of funny optimizations if it assumes single thread. Ones that can simply break your program.
Now I'm not entirely certain if synchronized is required here. My guess is no. I would add it anyway to be safe though. Or you can let java worry about the synchronization and use http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
Nothing new here, this is just a more explicit version of something #Cruncher already said:
You need synchronized whenever it is important for two or more fields in your program to be consistent with one another. Suppose you have two parallel lists, and your code depends on them both being the same length. That's called an invariant as in, the two lists are invariably the same length.
How can you write a method, append(x,y), that adds a new pair of values to the lists without temporarily breaking the invariant? You can't. The method must add one item to the first list, breaking the invariant, and then add the other item to the second list, fixing it again. There's no other way.
In a single-threaded program, that temporary broken state is no problem because no other method can possibly use the lists while append(x,y) is running. That's no longer true in a multithreaded program. In the worst case, append(x,y) could add x to the x list, and then the scheduler could suspend the thread at that exact moment to allow other threads to run. The CPUs could execute millions of instructions before append(x,y) gets to finish the job and make the lists right again. During all of that time, other threads would see the broken invariant, and possibly corrupt your data or crash the program as a result.
The fix is for append(x,y) to be synchronized on some object, and (this is the important part), for every other method that uses the lists to be synchronized on the same object. Since only one thread can be synchronized on a given object at a given time, it will not be possible for any other thread to see the lists in an inconsistent state.
So, if thread A calls append(x,y), and thread B tries to look at the lists "at the same time", will thread B see the what the lists looked like before or after thread A did its work? That's called a data race. And with only the synchronization that I have described so far, there's no way to know which thread will win. All we've done so far is to guarantee one particular invariant.
If it matters which thread wins the race, then that means that there is some higher-level invariant that also needs protection. You will have to add more synchronization to protect that one too. "Thread safety" -- two little words to name a subject that is both broad and deep.
Good Luck, and Have Fun!
// is synchronisation required?
public BigDecimal getSomeValue() {
return someValue;
}
// is synchronisation required?
public void setSomeValue(BigDecimal val) {
someValue = val;
}
I think Yes you are require to put the synchronization block because consider an example in which one thread is setting the value and at the same time other thread is trying to read from getter method, like here in the example you will see the syncronization block.So, if you take your variable inside the method then you must require the synchronization block.
In a nice article with some concurrency tips, an example was optimized to the following lines:
double getBalance() {
Account acct = verify(name, password);
synchronized(acct) { return acct.balance; }
}
If I understand that correctly, the point of the synchronization is to ensure that the value of acct.balance that are read by this thread is current and that any pending writes to the fields of the object in acct.balance are also written to main memory.
The example made me think a little: wouldn't it be more efficient to just declare acct.balance (i.e. the field balance of class Account) as volatile? It should be more efficient, save you all the synchronize on accesses to acct.balance and would not lock the whole acct object. Am I missing something?
You are correct. volatile provides a visibility guarantee. synchronized provides both a visibility guarantee AND serialisation of protected code sections. For VERY simple situations volatile is enough, however it is easy to get into trouble using volatile instead of synchronisation.
If you were to assume that Account has a way of adjusting its balance then volatile is not good enough
public void add(double amount)
{
balance = balance + amount;
}
Then we have a problem if balance is volatile with no other synchronization. If two threads were to try and call add() together you could have a "missed" update where the following happens
Thread1 - Calls add(100)
Thread2 - Calls add(200)
Thread1 - Read balance (0)
Thread2 - Read balance (0)
Thread1 - Compute new balance (0+100=100)
Thread2 - Compute new balance (0+200=200)
Thread1 - Write balance = 100
Thread2 - Write balance = 200 (WRONG!)
Obviously this is wrong because both threads read the current value and updated independently and then wrote it back (read, compute, write). volatile does not help here so you would need synchronized to ensure one thread completed the entire update before the other thread began.
I general find that if when writing some code I think "can I use volatile instead of synchronized" the answer might well be "yes" but the time/effort of figuring it out for sure and the danger of getting it wrong is not worth the benefit (minor performance).
As an aside a well written Account class would handle all the synch logic internally so callers don't have to worry about it.
Declaring Account as volatile is subjected to following issues and restrictions
1."Since other threads cannot see local variables, declaring local variables volatile is futile." Moreover If you try to declare a volatile variable in a method, you'll get a compiler error in some cases.
double getBalance() {
volatile Account acct = verify(name, password); //Incorrect ..
}
Declaring Account as volatile warns the compiler to fetch them fresh each time, rather than caching them in registers. This also inhibits certain optimizations that assume no other thread will change the values unexpectedly.
If you need synchronized to co-ordinate changes to variables from different threads,
volatile does not guarantee you atomic access,because accessing a volatile variable never holds a lock, it is not suitable for cases where we want to read-update-write as an atomic operation. Unless you are sure that acct = verify(name, password); is single atomic operation, you cannot guarantee excepted results
If variable acct is an object reference, then chances are it may be null .Attempting to synchronize on a null object will throw a NullPointerException using synchronized.
(because you're effectively synchronizing on the reference, not the actual object)
Where as volatile does not complain
Instead you could declare a boolean variable as volatile like here
private volatile boolean someAccountflag;
public void getBalance() {
Account acct;
while (!someAccountflag) {
acct = verify(name, password);
}
}
Note you cannot declare someAccountflag as synchronized, as
you can't synchronize on a primitive with synchronized, synchronized only works with object variables, where as primitive or object variable may be declared volatile
6.Class final static fields doesn't need to be volatile, JVM takes care of this problem. So the someAccountflag need not be even declared volatile if it is a final static
or you could use lazy singleton initialization making Account as a singleton object
and declare it as follows:
private final static AccountSingleton acc_singleton = new AccountSingleton ();
If multiple threads are modifying and accessing the data, synchronized guarantees data consistency among multiple threads .
if single thread is modifying the data and multiple threads try to read the latest value of data, use volatile construct.
But for above code, volatile does not guaranty memory consistency if multiple threds modify balance. AtomicReference with Double type serves your purpose.
Related SE question:
Difference between volatile and synchronized in Java
In the class below, is the method getIt() thread safe and why?
public class X {
private long myVar;
public void setIt(long var){
myVar = var;
}
public long getIt() {
return myVar;
}
}
It is not thread-safe. Variables of type long and double in Java are treated as two separate 32-bit variables. One thread could be writing and have written half the value when another thread reads both halves. In this situation, the reader would see a value that was never supposed to exist.
To make this thread-safe you can either declare myVar as volatile (Java 1.5 or later) or make both setIt and getIt synchronized.
Note that even if myVar was a 32-bit int you could still run into threading issues where one thread could be reading an out of date value that another thread has changed. This could occur because the value has been cached by the CPU. To resolve this, you again need to declare myVar as volatile (Java 1.5 or later) or make both setIt and getIt synchronized.
It's also worth noting that if you are using the result of getIt in a subsequent setIt call, e.g. x.setIt(x.getIt() * 2), then you probably want to synchronize across both calls:
synchronized(x)
{
x.setIt(x.getIt() * 2);
}
Without the extra synchronization, another thread could change the value in between the getIt and setIt calls causing the other thread's value to be lost.
This is not thread-safe. Even if your platform guarantees atomic writes of long, the lack of synchronized makes it possible that one thread calls setIt() and even after this call has finished it is possible that another thread can call getIt() and this call could return the old value of myVar.
The synchronized keyword does more than an exclusive access of one thread to a block or a method. It also guarantees that the second thread is informed about a change of a variable.
So you either have to mark both methods as synchronized or mark the member myVar as volatile.
There's a very good explanation about synchronization here:
Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.
No, it's not. At least, not on platforms that lack atomic 64-bit memory accesses.
Suppose that Thread A calls setIt, copies 32 bits into memory where the backing value is, and is then pre-empted before it can copy the other 32 bits.
Then Thread B calls getIt.
No it is not, because longs are not atomic in java, so one thread could have written 32 bits of the long in the setIt method, and then the getIt could read the value, and then setIt could set the other 32 bits.
So the end result is that getIt returns a value that was never valid.
It ought to be, and generally is, but is not guaranteed to be thread safe. There could be issues with different cores having different versions in CPU cache, or the store/retrieve not being atomic for all architectures. Use the AtomicLong class.
The getter is not thread safe because it’s not guarded by any mechanism that guarantees the most up-to-date visibility. Your choices are:
making myVar final (but then you can’t mutate it)
making myVar volatile
use synchronized to accessing myVar
AFAIK, Modern JVMs no longer split long and double operations. I don't know of any reference which states this is still a problem. For example, see AtomicLong which doesn't use synchronization in Sun's JVM.
Assuming you want to be sure it is not a problem then you can use synchronize both get() and set(). However, if you are performing an operation like add, i.e. set(get()+1) then this synchronization doesn't buy you much, you still have to synchronize the object for the whole operation. (A better way around this is to use a single operation for add(n) which is synchronized)
However, a better solution is to use an AtomicLong. This supports atomic operations like get, set and add and DOESN'T use synchronization.
Since it is a read only method. You should synchronize the set method.
EDIT : I see why the get method needs to be synchronized as well. Good job explaining Phil Ross.