here is my custom class for singleton pattern. in this code, I use double-checked locking as below. As I read many posts on some source, they say that double check is useful because it prevents two concurrent threads run at same times make two different objects.
public class DoubleCheckLocking {
public static class SearchBox {
private static volatile SearchBox searchBox;
// private constructor
private SearchBox() {}
// static method to get instance
public static SearchBox getInstance() {
if (searchBox == null) { // first time lock
synchronized (SearchBox.class) {
if (searchBox == null) { // second time lock
searchBox = new SearchBox();
}
}
}
return searchBox;
}
}
I still don't understand above code so much. What is the problem, if two threads together run same line of code when instance is null ?
if (searchBox == null) {
synchronized (SearchBox.class) {
if (searchBox == null) {
searchBox = new SearchBox();
}
}
}
When that appear. both two threads will see object is null. then both synchronize. and then, they check again, and still see it null. and create two different objects. OOOPS.
Please explain for me. What have I understand wrong ?
Thanks :)
No, since you are obtaining lock on the SearchBox.class, only one thread will enter the synchronized block at a time. So the first thread enters then finds searchBox is null and creates it and then leaves the synchronized block, then the second thread enter the block then it finds that the searchBox is not null because the first thread already created it so it will not create a new instance of searchBox.
The double checked pattern is used to avoid obtaining the lock every time the code is executed. If the call are not happening together then the first condition will fail and the code execution will not execute the locking thus saving resources.
Let's look at this code:
1 if (searchBox == null) {
2 synchronized (SearchBox.class) {
3 if (searchBox == null) {
4 searchBox = new SearchBox();
5 }
6 }
7 }
Let's try to reason about this. Let's say we have two threads A and B and let's assume that at least one of them reaches line 3 and observes searchBox == null is true. Two threads can not both be at line 3 at the same time because of the synchronized block. This is the key to understanding why double-checked locking works. So, it must the case that either A or B made it through synchronized first. Without loss of generality, say that that thread is A. Then, upon seeing searchBox == null is true, it will enter the body of the statement, and set searchBox to a new instance of SearchBox. It will then eventually exit the synchronized block. Now it will be B's turn to enter: remember, B was blocked waiting for A to exit. Now when it enters the block, it will observe searchBox. But A will have left just having set searchBox to a non-null value. Done.
By the way, in Java, the best way to implement a singleton is to use a single-element enum type. From Effective Java:
While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.
This double check lock is only necessary if you are worried about many threads calling the singleton simultaneously, or the cost of obtaining a lock in general.
Its purpose is to prevent unnecessary synchronization, thereby keeping your code fast in a multi-threaded environment.
Check out this link for more information.
If you are running in Java 1.5 or greater, and you use the volatile keyword in your double-check locked mechanism, it will work fine. As you are using the volatile keyword, your example is not broken according to the same link above.
if (searchBox == null) { //1
synchronized (SearchBox.class) {
if (searchBox == null) { //2
searchBox = new SearchBox();
}
}
}
}
If an instance was already created, don't do anything - avoid locking threads
The first thread that has acquired the lock checks and sees that there is no such object and creates it. It releases the lock and the second one can do the same - it has to check if the object exists because the first one may have created it.
So basically the outer if is used to prevent redundant locks - it lets all thread know that there is already an object and they don't need to lock/do anything. And the inner if is used to let a concurrent thread know whether another has already created the object or not.
Related
I need help in understanding the below code :
private Predicate composedPredicate = null;
public boolean evaluate(Task taskData) {
boolean isReadLock = false;
try{
rwl.readLock().lock();
isReadLock = true;
if (composedPredicate == null) {
rwl.readLock().unlock();
isReadLock = false;
rwl.writeLock().lock();
if (composedPredicate == null) {
//write to the "composedPredicate" object
}
}
}finally {
if (isReadLock) {
rwl.readLock().unlock();
}else{
rwl.writeLock().unlock();
}
}
return composedPredicate.test(taskData);
}
What will happen if we don't use Read Locks in the above code?
Like :
public boolean evaluate(Task taskData) {
//boolean isReadLock = false;
try{
//rwl.readLock().lock();
//isReadLock = true;
if (composedPredicate == null) {
//rwl.readLock().unlock();
//isReadLock = false;
rwl.writeLock().lock();
if (composedPredicate == null) {
//write to the "composedPredicate" object
}
}
}finally {
rwl.writeLock().unlock();
}
return composedPredicate.test(taskData);
}
Do we really need Read locks while we are only writing the data?
What is the difference between the above two codes?
Should we use Read locks even for accessing the object(composedPredicate) for null check?
The first code that you posted is a correct implementation of the double-checked locking approach in Java using a read/write lock.
Your second implementation without a read-lock is broken. The memory model allows writes to be reordering from the perspective of another thread seeing the result of the writes to memory.
What could happen is that you could be using a not-fully initialized instance of Predicate in the thread that is reading it.
Example with your code:
We have thread A and B both running evaluate and composedPredicate is null initially.
A: sees composedPredicate is null
A: write-locks
A: creates an instance of an implementation of Predicate
A: initializes this instance in the constructor
A: assigns the instance to the the shared variable composedPredicate
A: unlocks the write lock
B: sees composedPredicate is not null
B: runs composedPredicate.test(taskData);
HOWEVER, the compiler, the JVM, or the hardware architecture of your system reordered steps 4 and 5 of thread A, and assigned the address of the Predicate instance of the shared field before it was initialized (this is allowed by the Java Memory model)
composedPredicate.test(taskData); is run using a not-fully initialized instance and your code has random unexpected errors in production resulting in great losses to your company (potentially that happens .. depends on the system that you're building)
Whether or not the reordering of step 4 and 5 happens depends on many factors. Maybe it only does under heavy system load. It may not happen at all on your OS, hardware, version of JVM, etc. (But on the next version of the JVM, your OS, or when you move your application to a different physical machine, it may suddenly start happening)
Bad idea.
This code is simular to an old 'Singleton-pattern' wich makes use of the synchronozed blocks. E.g.
class Singleton
{
volatile Singleton s;
public static Singleton instance()
{
if(s == null)
{
synchronized(Singleton.class)
{
if(s == null)
s = new Singleton();
}
}
return s;
}
}
Notice the double 'null-check' where only the second one is synchronozed. The reason for doing the first 'null-check' is to prevent the blocking of threads if the instance() method is called (because when not null, it can proceed without synchronization).
Your first code is doing the same. First it checks if there is something assigned to composedPredicate. And if that isnt the case, only than will it aquire a writingLock (wich blocks all other Thread oposed to readLocks, which only blocks writeLocks).
The main difference with the 'singleton-pattern' and your code is that your value can be reassignes. This can only happen safly if it makes sure nobody is reading the value during modification. By removing the readLock you basically create a possibility that a thread may get undefined results (if not a crash) when accessing the composedPredicate while another Thread is modifying that same field.
So to answer your questions:
1. You dont need a readLock for writing, only a writeLock (wich will block all other Threads whonare trying to lock). But in this design-pattern you cannot leave it out.
2. & 3. See explanation above.
Hope this was enough to get a grasp of this pattern.
EDIT
As commented by Erwin Bolwidt , the above pattern is considered broken (without the 'volatile' keyword) due to compiler/CPU code optimization (where read/write actions may happen out of order). In the linked blog there are examples for alternatives/fixes for this problem. It turns out the 'volatile' keyword creates a barier which disallows reordering of read and write operations by either the compiler or CPU optimization, and thus 'fixes' the 'double-checked-locking' pattern described above.
In the examples mentioned for Out-of-order writes for double-checked locking scenarios (ref:
IBM article & Wikipedia Article)
I could not understand the simple reason of why Thread1 would come of out synchronized block before the constructor is fully initialized. As per my understanding, creating "new" and the calling constructor should execute in-sequence and the synchronized lock should not be release till all the work in not completed.
Please let me know what I am missing here.
The constructor can have completed - but that doesn't mean that all the writes involved within that constructor have been made visible to other threads. The nasty situation is when the reference becomes visible to other threads (so they start using it) before the contents of the object become visible.
You might find Bill Pugh's article on it helps shed a little light, too.
Personally I just avoid double-checked locking like the plague, rather than trying to make it all work.
The code in question is here:
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
Now the problem with this cannot be understood as long as you keep thinking that the code executes in the order it is written. Even if it does, there is the issue of cache synchronization across multiple processors (or cores) in a Symmetrical Multiprocessing architecture, which is the mainstream today.
Thread1 could for example publish the instance reference to the main memory, but fail to publish any other data inside the Singleton object that was created. Thread2 will observe the object in an inconsistent state.
As long as Thread2 doesn't enter the synchronized block, the cache synchronization doesn't have to happen, so Thread2 can go on indefinitely without ever observing the Singleton in a consistent state.
Thread 2 checks to see if the instance is null when Thread 1 is at //3 .
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;//4
}
At this point the memory for instance has been allocated from the heap and the pointer to it is stored in the instance reference, so the "if statement" executed by Thread 2 returns "false".
Note that because instance is not null when Thread2 checks it, thread 2 does not enter the synchronized block and instead returns a reference to a " fully constructed, but partially initialized, Singleton object."
There's a general problem with code not being executed in the order it's written. In Java, a thread is only obligated to be consistent with itself. An instance created on one line with new has to be ready to go on the next. There's no such oblgation to other threads. For instance, if fieldA is 1 and 'fieldB' is 2 going into this code on thread 1:
fieldA = 5;
fieldB = 10;
and thread 2 runs this code:
int x = fieldA;
int y = FieldB;
x y values of 1 2, 5 2, and 5 10 are all to be expected, but 1 10--fieldB was set and/or picked up before fieldA--is perfectly legal, and likely, as well. So double-checked locking is a special case of a more general problem, and if you work with multiple threads you need to be aware of it, particularly if they all access the same fields.
One simple solution from Java 1.5 that should be mentioned: fields marked volatile are guaranteed to be read from main memory immediately before being referenced and written immediately after. If fieldA and fieldB above were declared volatile, an x y value of 1 10 would not be possible. If instance is volatile, double-checked locking works. There's a cost to using volatile fields, but it's less than synchronizing, so the double-checked locking becomes a pretty good idea. It's an even better idea because it avoids having a bunch of threads waiting to synch while CPU cores are sitting idle.
But you do want to understand this (if you can't be talked out of multithreading). On the one hand you need to avoid timing problems and on the other avoid bringing your program to a halt with all the threads waiting to get into synch blocks. And it's very difficult to understand.
I came across a code like this
synchronized(obj) {
obj = new Object();
}
Something does not feel right about this , I am unable to explain, Is this piece of code OK or there is something really wrong in it, please point it out.
Thanks
It's probably not what you want to do. You're synchronizing on an object that you're no longer holding a reference to. Consider another thread running this method: they may enter and try to hit the lock at the moment after the reference to obj has been updated to point to the new object. At that point, they're synchronizing on a different object than the first thread. This is probably not what you're expecting.
Unless you have a good reason not to, you probably want to synchronize on a final Object (for visibility's sake.) In this case, you would probably want to use a separate lock variable. For example:
class Foo
{
private final Object lock = new Object();
private Object obj;
public void method()
{
synchronized(lock)
{
obj = new Object();
}
}
}
If obj is a local variable and no other thread is evaluating it in order to acquire a lock on it as shown here then it doesn't matter. Otherwise this is badly broken and the following applies:
(Posting this because the other answers are not strongly-worded enough --"probably" is not sufficient here -- and do not have enough detail.)
Every time a thread encounters a synchronized block,
before it can acquire the lock, it has to figure out what object it needs to lock on, by evaluating the expression in parens following the synchronized keyword.
If the reference is updated after the thread evaluates this expression, the thread has no way of knowing that. It will proceed to acquire the lock on the old object that it identified as the lock before. Eventually it enters the synchronized block locking on the old object, while another thread (that tries to enter the block after the lock changed) now evaluates the lock as being the new object and enters the same block of the same object holding the new lock, and you have no mutual exclusion.
The relevant section in the JLS is 14.19. The thread executing the synchronized statement:
1) evaluates the expression, then
2) acquires the lock on the value that the expression evaluates to, then
3) executes the block.
It doesn't revisit the evaluation step again at the time it successfully acquires the lock.
This code is broken. Don't do this. Lock on things that don't change.
This is a case where someone might think what they are doing is OK, but it probably isn't what they intended. In this case, you are synchronizing on the current value in the obj variable. Once you create a new instance and place it in the obj variable, the lock conditions will change. If that is all that is occurring in this block, it will probably work - but if it is doing anything else afterwards, the object will not be properly synchronized.
Better to be safe and synchronize on the containing object, or on another mutex entirely.
It's a uncommon usage but seems to be of valid in same scenarios. One I found in the codebase of JmDNS:
public Collection<? extends DNSEntry> getDNSEntryList(String name) {
Collection<? extends DNSEntry> entryList = this._getDNSEntryList(name);
if (entryList != null) {
synchronized (entryList) {
entryList = new ArrayList<DNSEntry>(entryList);
}
} else {
entryList = Collections.emptyList();
}
return entryList;
}
What it does is to synchonize on the returned list so this list does not get modified by others and then makes a copy of this list. In this special situation the lock is only needed for the original object.
I know that concurrently accessing the same object from different threads, without synchronisation, is in general a bad thing. But what about this case:
I have multiple threads running (consider two, ThreadA & ThreadB). I also have this static class to keep count of the number of times a Thread does something.
public class Counter {
static private int counter=0;
static public void incCounter() {
counter++;
}
}
What happens if ThreadA and ThreadB both call Counter.incCounter()?
It's not safe.
Each thread will attempt to read counter, add one to it, and write back the result. You're not guaranteed what order these reads and writes happen in, or even if the results are visible to each thread.
In particular, one failure case would be that each thread reads the value 0, increments it to 1, and writes back the value 1. This would give the counter the value 1 even after two threads attempted to increment it.
Consider using AtomicInteger.incrementAndGet() instead.
Its value will either be 1 or 2. There's no difference between static and non static variables in this context.
It doesn't matter whether it's a static object or an instance: if you change it from multiple threads, you're going to have a problem.
to avoid conflict use the keyword synchronized.
public class Counter {
static private int counter=0;
public static synchronized void incCounter() {
counter++;
}
}
this keywords allows only one thread for time to call incCounter().
Dave is correct, but a quick fix is just to add the "synchronized" keyword to that method description; if multiple threads call that method, they will block at the method boundary until the one inside (that won the race) increments and exists, then the 2nd caller will enter.
This is a lot like designing a good "getInstance()" method on a Singleton class; you typically want it to be synchronized so you don't have the case where 2+ threads enter the method, ALL see that the "instance" is null, and then ALL create a new instance, assign it to the local member and return it.
Your threads can end up with different references to the "same" instance in that case. So you synchronize the code block, only let the first thread create the instance if it's null, and otherwise ALWAYS return the same one to all callers.
The if(instance == null) check plus the return are cheap; on the order of microseconds I believe for the future calls to getInstance (or in your example incCounter) so no need to shy away from the synchronized keyword if you need it; that's what it is for.
That being said, if you can't spare microseconds... well then you might be using the wrong language :)
What could be the understanding of the following?
I have gone through this post at SO but still at a loss to assemble it.
code1:
synchronized(this){
// some code
}
code2:
Object lock = new Object();
synchronized(lock){
// some code
}
Any tutorial, or some links to explain synchronized like they explain it to a child?
Basically there is a "lock" associated with every object in Java.
When a thread reaches a call to synchronized(something), it has to acquire the lock of something before continuing. If you want to allow only one thread at a time to modify the state of an object, the most obvious thing is to synchronize on the lock of that object. If different methods are allowed to be called in parallel, you need different locks for that.
If you write synchronized(this), or simply synchronized, the thread must acquire the lock associated with the current object (of which method is called).
Note that since Java 5.0 there concurrent package provides proper locks which can be used instead of synchronization.
One thing not mentioned in the otherwise excellent answers already given is that difference between code1 and code2. In code1, the synchronization is on the instance of the object in which the code is found, and in code2, it's on the specific lock object within the object.
If there's only the two synchronized blocks in the enclosing class, there's no functional difference between the two, but consider this:
class CodeOneClass {
...
synchronized(this) { // or merely "synchronized" - it defaults to this
first protected code block
}
...
synchronized(this) {
second protected code block
}
...
}
class CodeTwoClass {
...
Object lock1 = new Object();
synchronized(lock1) {
first protected code block
}
...
Object lock2 = new Object();
synchronized(lock2) {
second protected code block
}
...
}
If two threads are trying to use the same instance of CodeOneClass, only one of them can be in either of the two protected code blocks at the same time.
But with the second idiom, you have the flexibility to say that it's safe for one thread to be in the first protected block, and another to be in the other. Note that if the locks were the same (both synchronizing on the same lock object), the behavior would be as the first.
There are other differences. Some writers are beginning to point out issues with synchronized(this) - I would point you to another post here on SO:
Avoid synchronized(this) in Java?
I highly recommend reading it, and the three posts it links to.
Putting code within a synchronized block essentially means, "Once this code starts running, other code that needs to use this object cannot run at the same time."
So, if Thread #2 is executing code in your code2 block, when it comes to the synchronized(lock) code it has to effectively look around at all the other threads to make sure nobody else is running "synchronized" code with the lock object at the moment. Thread #1 is certainly running some code at the same time, but it might be completely unrelated code. If so, it's safe for Thread #2 to start running your "some code" stuff.
Meanwhile, if Thread #1 gets to the synchronized(this) block, it too has to pause and see if any other threads are using this. If this is the same object as lock, we have a problem. We were told that only one thread can possibly use that object (in a synchronized block) at the same time. Yet Thread #2 is already using it. Thread #1 will just have to wait... and wait... and wait... until eventually Thread #2 finishes. Then we can proceed.
The end result is that only one synchronized block can run at a time (with a particular object, of course).
Suppose you have an Account object which has a method:
void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
if (accountBalance >= debitAmount) {
accountBalance -= debitAmount;
beneficiary.credit(debitAmount);
}
else {
throw new InsufficientFundsException();
}
}
Now suppose you have an account with a balance of 100 euros, and you get two attempts to debit it by 70 euros. If the two debits occur at the same time, you can get a race condition like this:
First debit checks account balance: 100 >= 70, so succeeds
Second debit checks account balance: 100 >= 70, so succeeds
First debit executes; account balance becomes 30
Second debit executes; account balance becomes -40. Shouldn't be allowed
We can prevent this dire state of affairs by synchronizing on the Account object's lock:
void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
synchronized (this) {
if (accountBalance >= debitAmount) {
accountBalance -= debitAmount;
beneficiary.credit(debitAmount);
}
else {
throw new InsufficientFundsException();
}
}
}
This makes sure that the test on the account balance and the debit can't be interrupted by another test on the account balance.
The Sun Java tutorial is a good place to start for information on concurrency and locking.