I faced the following code in our project:
synchronized (Thread.currentThread()){
//some code
}
I don't understand the reason to use synchronized on currentThread.
Is there any difference between
synchronized (Thread.currentThread()){
//some code
}
and just
//some code
Can you provide an example which shows the difference?
UPDATE
more in details this code as follows:
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(timeInterval);
}
It looks like just Thread.sleep(timeInterval). Is it truth?
consider this
Thread t = new Thread() {
public void run() { // A
synchronized (Thread.currentThread()) {
System.out.println("A");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
}
};
t.start();
synchronized (t) { // B
System.out.println("B");
Thread.sleep(5000);
}
blocks A and B cannot run simultaneously, so in the given test either "A" or "B" output will be delayed by 5 secs, which one will come first is undefined
Although this is almost definitely an antipattern and should be solved differently, your immediate question still calls for an answer. If your entire codebase never acquires a lock on any Thread instance other than Thread.currentThread(), then indeed this lock will never be contended. However, if anywhere else you have
synchronized (someSpecificThreadInstance) { ... }
then such a block will have to contend with your shown block for the same lock. It may indeed happen that the thread reaching synchronized (Thread.currentThread()) must wait for some other thread to relinquish the lock.
Basically there is no difference between the presence and absence of the synchronized block. However, I can think of a situation that could give other meaning to this usage.
The synchronized blocks has an interesting side-effect of causing a memory barrier to be created by the runtime before entering and after leaving the block. A memory barrier is a special instruction to the CPU that enforces all variables that are shared between multiple threads to return their latest values. Usually, a thread works with its own copy of a shared variable, and its value is visible to this thread only. A memory barrier instructs the thread to update the value in a way so that the change is visible to the other threads.
So, the synchronized block in this case does not do any locking (as there will be no real case of lock and wait situation, at lest none I can think of)(unless the use-case mentioned in this answer is addressed), but instead it enforces the values of the shared fields to return their latest value. This, however, is true if the other places of the code that work with the variables in question also uses memory barriers (like having the same synchronized block around the update/reassignment operations). Still, this is not a solution for avoiding race conditions.
If you're interested, I recommend you to read this article. It is about memory barriers and locking in C# and the .NET framework, but the problem is similar for Java and the JVM (except for the behavior of volatile fields). It helped me a lot in understanding how threads, volatile fields and locks work in general.
One must take into account some serious considerations in this approach, that were mentioned in comments below this answer.
The memory barrier does not imply locking. The access will still be non-synchronized and a subject to race conditions and other potential issues one may encounter. The only benefit is the thread being able to read the latest values of the shared memory fields, without the use of locks. Some practices use similar approaches if the working thread only reads from values and it does only care for them to be the most present ones, while avoiding the overhead of locks - a use case could be a high-performance simultaneous data processing algorithm.
The approach above is unreliable. As per Holger's comment, the compiler could eliminate the lock statements when optimizing, as it could consider them unnecessary. This will also remove the memory barriers. The code then will not issue a lock, and it will not work as expected if a lock was meant to be used, or the purpose was to create a memory barrier.
The approach above is also unreliable because the runtime JVM can remove synchronization when it can prove the monitor will never be acquired by another thread, which is true of this construct if the code never synchronizes on another thread object which is not the current thread's thread object. So even if it works during testing on system A, it might fail under another JVM on system B. Even worse, the code could work for a while and then cease working as optimizations are applied.
The intentions of the code as it stays now are ambiguous, so one should use more explicit and expressive means to achieve its effect (see Marko Topolnik's comment for reference).
You are implementing a recursive mutex.
i.e. the same thread can enter the synchronisation block, but not other threads.
Related
I'm trying to understand the need for volatile in double-checked locking (I'm aware there are better ways than DCL though) I've read a few SO questions similar to mine, but none seem to explain what I'm looking for. I've even found some upvoted answers on SO that have said volatile is not needed (even when the object is mutable) however, everything I've read says otherwise.
What I want to know is why volatile is necessary in DCL if synchronized creates a happens-before relationship and prevents reordering?
Here is my understanding of how DCL works and an example:
// Does not work
class Foo {
private Helper helper = null; // 1
public Helper getHelper() { // 2
if (helper == null) { // 3
synchronized(this) { // 4
if (helper == null) { // 5
helper = new Helper(); // 6
} // 7
} // 8
} // 9
return helper; // 10
}
This does not work because the Helper object is not immutable or volatile and we know that
volatile causes every write to be flushed to memory and for every read to come from memory. This is important so that no thread sees a stale object.
So in the example I listed, it's possible for Thread A to begin initializing a new Helper object at Line 6. Then Thread B comes along and see a half initialized object at line 3. Thread B then jumps to line 10 and returns a half initialized Helper object.
Adding volatile fixes this with a happens before relationship and no reordering can be done by the JIT compiler. So the Helper object cannot be written to the helper reference until it is fully constructed (?, at least this is what I think it is telling me...).
However, after reading JSR-133 documentation, I became a bit confused. It states
Synchronization ensures that memory writes by a thread before or
during a synchronized block are made visible in a predictable manner
to other threads which synchronize on the same monitor. After we exit
a synchronized block, we release the monitor, which has the effect of
flushing the cache to main memory, so that writes made by this thread
can be visible to other threads. Before we can enter a synchronized
block, we acquire the monitor, which has the effect of invalidating
the local processor cache so that variables will be reloaded from main
memory. We will then be able to see all of the writes made visible by
the previous release.
So synchronized in Java creates a memory barrier and a happens before relationship.
So the actions are being flushed to memory, so it makes me question why volatile is needed on the variable.
The documentation also states
This means that any memory operations which were visible to a thread
before exiting a synchronized block are visible to any thread after it
enters a synchronized block protected by the same monitor, since all
the memory operations happen before the release, and the release
happens before the acquire.
My guess as to why we need the volatile keyword and why synchronize is not enough, is because the memory operations are not visible to other threads until Thread A exits the synchronized block and Thread B enters the same block on the same lock.
It's possible that Thread A is initializing the object at line 6 and Thread B comes along at Line 3 before there is a flush by Thread A at Line 8.
However, this SO answer seems to contradict that as the synchronized block prevents reordering "from inside a synchronized block, to outside it"
If helper is not null, what ensures that the code will see all the effects of the construction of the helper? Without volatile, nothing would do so.
Consider:
synchronized(this) { // 4
if (helper == null) { // 5
helper = new Helper(); // 6
} // 7
Suppose internally this is implemented as first setting helper to a non-null value and then calling the constructor to create a valid Helper object. No rule prevents this.
Another thread may see helper as non-null but the constructor hasn't even run yet, much less made its effects visible to another thread.
It is vital not to permit any other thread to see helper set to a non-null value until we can guarantee that all consequences of the constructor are visible to that thread.
By the way, getting code like this correct is extremely difficult. Worse, it can appear to work fine 100% of the time and then suddenly break on a different JVM, CPU, library, platform, or whatever. It is generally advised that writing this kind of code be avoided unless proven to be needed to meet performance requirements. This kind of code is hard to write, hard to understand, hard to maintain, and hard to get right.
#David Schwartz's answer is pretty good but there is one thing that I'm not sure is stated well.
My guess as to why we need the volatile keyword and why synchronize is not enough, is because the memory operations are not visible to other threads until Thread A exits the synchronized block and Thread B enters the same block on the same lock.
Actually not the same lock but any lock because locks come with memory barriers. volatile is not about locking but it is around crossing memory barriers while synchronized blocks are both locks and memory barriers. You need the volatile because even though Thread A has properly initialized the Helper instance and published it to helper field, Thread B needs to also cross a memory barrier to ensure that it sees all of the updates to Helper.
So in the example I listed, it's possible for Thread A to begin initializing a new Helper object at Line 6. Then Thread B comes along and see a half initialized object at line 3. Thread B then jumps to line 10 and returns a half initialized Helper object.
Right. It is possible that Thread A might initialize the Helper and publish it before it hits the end of the synchronized block. There is nothing stopping it from happening. And because the JVM is allowed to reorder the instructions from the Helper constructor until later, it could be published to helper field but not be fulling initialized. And even if Thread A does reach the end of the synchronized block and Helper then gets fully initialized, there is still nothing that ensures that Thread B sees all of the updated memory.
However, this SO answer seems to contradict that as the synchronized block prevents reordering "from inside a synchronized block, to outside it"
No, that answer is not contradictory. You are confusing what happens with just Thread A and what happens to other threads. In terms of Thread A (and central memory), exiting the synchronized block makes sure that Helper's constructor has fully finished and published to the helper field. But this means nothing until Thread B (or other threads) also cross a memory barrier. Then they too will invalidate the local memory cache and see all of the updates.
That's why the volatile is necessary.
The following method is a method of class SomeType-- the type it is taking as its argument.
The line comments indicate the line #s.
synchronized void someMethod(SomeType other) { // line 1
// line 2
synchronized (other) { // line 3
//...do stuff // line 4
}
}
The block indicated as "line 4" has calls to some other synchronized methods of both this
and other, and this code is intended for avoiding deadlocks.
However -- suppose both a.someMethod(b) and b.someMethod(a) are invoked concurrently, where a and b are different instances.
Further suppose that b.someMethod(a) is invoked right after a.someMethod(b) is, and they both are held up
at line 2-- each of a and b acquired its own lock and waiting for the other's lock to proceed.
Can/not this happen?
If so - on which jdk implementations? This looks like something that depends on the specific implementation unless it
is explicitly in the jdk specifications.
TIA
Yes, the deadlock you describe can happen. How often it happens may be dependent on the specifics of the threading code; these days, you are most likely using the native threading of the operating system, so it would be more dependent on the native OS than on the JDK/JRE. Deadlock is likely possible on most platforms, though, so you should guard against it in your code.
If you think contention for the method will be low or if you don't care about performance, you could synchronize on a static member or on the class itself, rather than synchronizing on the objects. If you do care about performance and think contention will be significant, you will need to figure out a way to ensure that the monitors are locked in the same order independent of which object the method is being called on and which is the method argument.
Consider two methods a() and b() that cannot be executed at the same time.
The synchronized key word can be used to achieve this as below. Can I achieve the same effect using AtomicBoolean as per the code below this?
final class SynchonizedAB {
synchronized void a(){
// code to execute
}
synchronized void b(){
// code to execute
}
}
Attempt to achieve the same affect as above using AtomicBoolean:
final class AtomicAB {
private AtomicBoolean atomicBoolean = new AtomicBoolean();
void a(){
while(!atomicBoolean.compareAndSet(false,true){
}
// code to execute
atomicBoolean.set(false);
}
void b(){
while(!atomicBoolean.compareAndSet(false,true){
}
// code to execute
atomicBoolean.set(false);
}
}
No, since synchronized will block, while with the AtomicBoolean you'll be busy-waiting.
Both will ensure that only a single thread will get to execute the block at a time, but do you want to have your CPU spinning on the while block?
It depends on what you are planning to achieve with original synchronized version of the code. If synchronized was added in original code just to ensure only one thread will be present at a time in either a or b method then to me both version of the code looks similar.
However there are few differences as mentioned by Kayaman. Also to add more diffs, with synchronized block you will get memory barrier which you will miss with Atomic CAS loops. But if the body of the method doesn't need such barrier then that difference gets eliminated too.
Whether Atomic cas loop performs better over synchronized block or not in indivisual case that only performance test can tell but this is the same technique being followed at multiple places in concurrent package to avoid synchronization at block level.
From a behavioral standpoint, this appears to be a partial replacement for Java's built-in synchronization (monitor locks). In particular, it appears to provide correct mutual exclusion which is what most people are after when they're using locks.
It also appears to provide the proper memory visibility semantics. The Atomic* family of classes has similar memory semantics to volatile, so releasing one of these "locks" will provide a happens-before relationship to another thread's acquisition of the "lock" which will provide the visibility guarantee that you want.
Where this differs from Java's synchronized blocks is that it does not provide automatic unlocking in the case of exceptions. To get similar semantics with these locks, you'd have to wrap the locking and usage in a try-finally statement:
void a() {
while (!atomicBoolean.compareAndSet(false, true) { }
try {
// code to execute
} finally {
atomicBoolean.set(false);
}
}
(and similar for b)
This construct does appear to provide similar behavior to Java's built-in monitor locks, but overall I have a feeling that this effort is misguided. From your comments on another answer it appears that you are interested in avoiding the OS overhead of blocking threads. There is certainly overhead when this occurs. However, Java's built-in locks have been heavily optimized, providing very inexpensive uncontended locking, biased locking, and adaptive spin-looping in the case of short-term contention. The last of these attempts to avoid OS-level blocking in many cases. By implementing your own locks, you give up these optimizations.
You should benchmark, of course. If your performance is suffering from OS-level blocking overhead, perhaps your locks are too coarse. Reducing the amount of locking, or splitting locks, might be a more fruitful way to reduce contention overhead than to try to implement your own locks.
Question: What is the cost of re-entering a synchronized block when the monitor is already locked?
For example:
Object lock;
void outer()
{
synchronized (lock)
{
innerOne();
innerTwo();
}
}
void innerOne() { synchronized (lock) { /* ... */ } }
void innerTwo() { synchronized (lock) { /* ... */ } }
The intention of the above is that innerOne and innerTwo are always called while the thread is synchronised on lock.
If there is a non-negligible cost is there any method that can be called to put in an assert statement? The closest I can find is to call lock.notify(), and catch IllegalMonitorStateException, e.g.
boolean isMonitorHeld(final Object object)
{
try { object.notify(); return true }
catch (final IllegalMonitorStateException e) { return false; }
}
Which would be used like:
void innerOne() { assert isMonitorHeld(lock); /* ... */ }
Are there any comments on the style of the two options, or any alternatives?
EDIT
I'm hoping for more comprehensive answers than just 'time it and see'. I don't have the ability to foresee all of the potential situations my code could encounter and then even create a test to exhibit these situations. I'd like to understand how the synchronisation mechanism works to understand how it might perform in different circumstances. I understand synchronisation may be implemented differently on the different platforms. In which case is it different (primarily on Solaris and Linux OSes)?
Intuitively, I don't believe that re-entering a synchronised block will have a noticeable cost as most of the articles I can find imply that uncontended locks are cheap. However, it doesn't feel right to add the synchronised blocks in these methods as it gives the impression they can be called without having first synchronised on the lock. The assert gives a better idea of the intention, but it looks like a fairly ugly hack. I'd like to know if there's a good reason that there isn't a more legitimate alternative.
So your question is asking one thing, and then the body of your question is asking something else. I can most certainly say your algorithm to test if a thread hold a lock will be very slow. Much slower than just not checking. Throwing exceptions like this is expensive. Rule number one about exceptions. Don't use Exceptions for regular flow control in your program. Exceptions are a form of control flow structure, but you should only use them for error flow control. Mainly because whenever you throw an exception it must gather up the stack trace to place that into the exception. That is an expensive operation. You should definitely use exceptions, but only for what they are designed for: error flow control.
If you want to test if the currentThread holds a lock you should use Thread.holdsLock(Object monitor)
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#holdsLock(java.lang.Object)
As for what is the cost of re-entering into a synchronize block for the currentThread is already a holder. I don't have a very detailed answer for that. I suspect its whatever the cost of calling holdsLock is. That's probably the first check, and if it returns false then there is more cost with requesting this thread be add to the list of threads waiting on this object monitor. If it's true it jumps right into the block. Java threading, if it wants to be performant, the answer to this question better be fast as hell for the lock owner. For threads not owning a lock its certainly more expensive. If there is an answer to what the exact algorithm is I bet its in the "Taming Threads" book or Java spec.
Measure it. On my system there might not be a difference. On yours there might. The system you deploy to might be more different still.
I see this code quite frequently in some OSS unit tests, but is it thread safe ? Is the while loop guaranteed to see the correct value of invoc ?
If no; nerd points to whoever also knows which CPU architecture this may fail on.
private int invoc = 0;
private synchronized void increment() {
invoc++;
}
public void isItThreadSafe() throws InterruptedException {
for (int i = 0; i < TOTAL_THREADS; i++) {
new Thread(new Runnable() {
public void run() {
// do some stuff
increment();
}
}).start();
}
while (invoc != TOTAL_THREADS) {
Thread.sleep(250);
}
}
No, it's not threadsafe. invoc needs to be declared volatile, or accessed while synchronizing on the same lock, or changed to use AtomicInteger. Just using the synchronized method to increment invoc, but not synchronizing to read it, isn't good enough.
The JVM does a lot of optimizations, including CPU-specific caching and instruction reordering. It uses the volatile keyword and locking to decide when it can optimize freely and when it has to have an up-to-date value available for other threads to read. So when the reader doesn't use the lock the JVM can't know not to give it a stale value.
This quote from Java Concurrency in Practice (section 3.1.3) discusses how both writes and reads need to be synchronized:
Intrinsic locking can be used to guarantee that one thread sees the effects of another in a predictable manner, as illustrated by Figure 3.1. When thread A executes a synchronized block, and subsequently thread B enters a synchronized block guarded by the same lock, the values of variables that were visible to A prior to releasing the lock are guaranteed to be visible to B upon acquiring the lock. In other words, everything A did in or prior to a synchronized block is visible to B when it executes a synchronized block guarded by the same lock. Without synchronization, there is no such guarantee.
The next section (3.1.4) covers using volatile:
The Java language also provides an alternative, weaker form of synchronization, volatile variables, to ensure that updates to a variable are propagated predictably to other threads. When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
Back when we all had single-CPU machines on our desktops we'd write code and never have a problem until it ran on a multiprocessor box, usually in production. Some of the factors that give rise to the visiblity problems, things like CPU-local caches and instruction reordering, are things you would expect from any multiprocessor machine. Elimination of apparently unneeded instructions could happen for any machine, though. There's nothing forcing the JVM to ever make the reader see the up-to-date value of the variable, you're at the mercy of the JVM implementors. So it seems to me this code would not be a good bet for any CPU architecture.
Well!
private volatile int invoc = 0;
Will do the trick.
And see Are java primitive ints atomic by design or by accident? which sites some of the relevant java definitions. Apparently int is fine, but double & long might not be.
edit, add-on. The question asks, "see the correct value of invoc ?". What is "the correct value"? As in the timespace continuum, simultaneity doesn't really exist between threads. One of the above posts notes that the value will eventually get flushed, and the other thread will get it. Is the code "thread safe"? I would say "yes", because it won't "misbehave" based on the vagaries of sequencing, in this case.
Theoretically, it is possible that the read is cached. Nothing in Java memory model prevents that.
Practically, that is extremely unlikely to happen (in your particular example). The question is, whether JVM can optimize across a method call.
read #1
method();
read #2
For JVM to reason that read#2 can reuse the result of read#1 (which can be stored in a CPU register), it must know for sure that method() contains no synchronization actions. This is generally impossible - unless, method() is inlined, and JVM can see from the flatted code that there's no sync/volatile or other synchronization actions between read#1 and read#2; then it can safely eliminate read#2.
Now in your example, the method is Thread.sleep(). One way to implement it is to busy loop for certain times, depending on CPU frequency. Then JVM may inline it, and then eliminate read#2.
But of course such implementation of sleep() is unrealistic. It is usually implemented as a native method that calls OS kernel. The question is, can JVM optimize across such a native method.
Even if JVM has knowledge of internal workings of some native methods, therefore can optimize across them, it's improbable that sleep() is treated that way. sleep(1ms) takes millions of CPU cycles to return, there is really no point optimizing around it to save a few reads.
--
This discussion reveals the biggest problem of data races - it takes too much effort to reason about it. A program is not necessarily wrong, if it is not "correctly synchronized", however to prove it's not wrong is not an easy task. Life is much simpler, if a program is correctly synchronized and contains no data race.
As far as I understand the code it should be safe. The bytecode can be reordered, yes. But eventually invoc should be in sync with the main thread again. Synchronize guarantees that invoc is incremented correctly so there is a consistent representation of invoc in some register. At some time this value will be flushed and the little test succeeds.
It is certainly not nice and I would go with the answer I voted for and would fix code like this because it smells. But thinking about it I would consider it safe.
If you're not required to use "int", I would suggest AtomicInteger as an thread-safe alternative.