Does the HotSpot JVM (in Oracle JDK 7 & 8) optimize for nested synchronized blocks that synchronize on the same object?
e.g., is the first code listing (class A) just as efficient as the second code listing (class B)? (class B avoids the nested synchronized (x) that occurs in class A)
public class A {
private final Object x = new Object();
public void a() {
synchronized (x) {
// code snippet 1
b();
// code snippet 2
}
}
public void b() {
synchronized (x) {
// code snippet 3
}
}
}
public class B {
private final Object x = new Object();
public void a() {
synchronized (x) {
// code snippet 1
c();
// code snippet 2
}
}
public void b() {
synchronized (x) {
c();
}
}
private void c() {
// code snippet 3
}
}
Yes, there is even a VM option for that appeared in JDK 7 (on by default):
-XX:+EliminateNestedLocks
However, it seems to work only when monitor object is static final or when locking on this object.
In cases when b is short enough to be inlined, I hope so. Otherwise no, as the inter-procedural analysis is too complicated and the gain limited (what can't be inlined takes probably so long that some overhead is acceptable). But then you can still profit from biased locking.
This is just a guess, but even JDK6 does lock coarsening, which can be thought of as a more complicated version of what you're asking about. After inlining we have
public void a() {
synchronized (x) {
// code snippet 1
synchronized (x) {
// code snippet 3
}
// code snippet 2
}
}
while lock coarsening starts with something like
public void a() {
synchronized (x) {
// code snippet 1
}
synchronized (x) {
// code snippet 3
}
synchronized (x) {
// code snippet 2
}
}
This is a more complicated case as here joining the synchronized blocks can reduce throughput, while in your case there's absolutely nothing to lose.
Related
Consider the following 2 examples:
Example 1:
Class A {
private final B b = new B();
public synchronized void m1() {
b.m2();
}
}
Class B {
public void m2() {
// do something
}
}
Example 2:
Class A {
B b = new B();
public synchronized void m1() {
b.m2();
}
}
Class B {
public synchronized void m2() {
// do something
}
}
Assuming B.m2() is only called in A.m1(),
what's the cost of synchronizing B.m2() if it's already guarded by A.m1()? i.e. Does Example 2 add any overhead compared to Example 1? Does the JVM optimize Example 2 to make it look like Example 1?
If you synchronize m2, there would be some overhead involved since when entering m2 the thread would still have to acquire the lock on the b object (event if the lock would be always free).
The JVM might figure out the synchronization is redundant and optimize it (i.e. remove the synchronized from m2) if escape analysis in enabled. If the code would get optimized, there would be no performance difference. The optimizations that remove redundant synchronization are called lock elision or lock coarsening.
For more details on escape analysis please see the following link.
I am learning how to work with threads and I ran into this question that with a given code I need to say what whether a certain thread will or will not be able to access a certain function.
Here is the code :
public class InsideClass{}
public class SyncClass{
private InsideClass in1;
private InsideClass in2;
public SyncClass(InsideClass i, InsideClass i2){ in1 = i; in2 = i2; }
public synchronized void func1() { System.out.println("in func1"); }
public void func2() { synchronized(in1) { System.out.println("in func2"); }}
public static synchronized void func3() { System.out.println("in func3"); }
public void func4() { synchronized(in2) { System.out.println("in func4"); }}
public synchronized void func5() {
synchronized(in1) {
synchronized(in2){ System.out.println("in func5"); }}
}}
public class MyThread extends Thread{
private SyncClass sc;
public MyThread(SyncClass s) {
sc = s;
}
public void run(){
sc.func1();
sc.func2();
SyncClass.func3();
sc.func4();
sc.func5();
}
}
public class Sys {
public static void main(String[] args) {
InsideClass in1 = new InsideClass();
InsideClass in2= new InsideClass();
SyncClass s1 = new SyncClass(in1,in2);
SyncClass s2 = new SyncClass(in2,in1);
MyThread t1 = new MyThread(s1);
MyThread t2 = new MyThread(s2);
t1.start();
t2.start();
}
}
The question goes like this, assuming that t1 is preforming task(i) (i=1,2,3,4), will t2 be able to preform func(i+1) or will it get blocked? explain.
I wrote the full question just in case it wasn't clear.
1) Assuming that t1 is preforming func1
a) Will t2 be able to preform func1?
b) Will t2 be able to preform func2?
c) Will t2 be able to preform func3?
d) Will t2 be able to preform func4?
2) Assuming that t1 is preforming func2.
a) Will t2 be able to preform func2?
b) Will t2 be able to preform func3?
c) Will t2 be able to preform func4?
3) Assuming that t1 is preforming func3
a) Will t2 be able to preform func3?
b) Will t2 be able to preform func4?
4) Assuming that t1 is preforming func4
a) Will t2 be able to preform func4?
5) func5 has a unique implementation.
a) How many different locks are cought by this method? Specify who they are.
b) What is the problem that comes up at func5? How would you solve this problem?
I'm not looking for answers to all these questions (even though it would be nice just in case) , but I would like to get an explanation of what is the meaning of an object (in this example in1/in2) inside a synchronized block, when 2 other object are initialized with these objects (s1,s2). If t1 is preforming func1 which is synchronized, how does that effect the attempt to preform func2? (how does the fact that s1 and s2 were initialized with the same objects inflect this issue).
I hope my question was clear enough. Thanks!
A synchronized statement acquires the intrinsic lock of the given object, then performs its body, and then releases the lock.
Object lock = new Object();
synchronized(lock) {
...body...
}
The Java Runtime Environment (JRE) will never allow two threads to acquire the intrinsic lock of the same object at the same time. If one thread acquires the lock, then the second thread to attempt it will be blocked until the first thread releases the lock.
It's important to know that the lock will be released no matter how the thread exits the ...body.... It doesn't matter whether it returns, whether it breaks, whether it simply runs off the end, or whether it throws an exception. The lock will be released in any case.
There's a shortcut way to write a member function whose entire body is synchronized.
This:
class MyClass {
synchronized void foobar(...args...) { ...body... }
}
Means exactly the same as this:
class MyClass {
void foobar(...args...) {
synchronized(this) { ...body... }
}
}
And the same goes for a synchronized static function, except that it synchronizes on the class object instead.
This:
class MyClass {
synchronized static void foobar(...args...) { ...body... }
}
Means exactly the same as this:
class MyClass {
static void foobar(...args...) {
synchronized(MyClass.class) { ...body... }
}
}
It's important to remember the difference between a variable and an object. Two threads can enter a synchronized(foo){...} block at the same time if the variable foo refers to two different objects in the two different contexts. (Think carefully about your in1 and in2 member variables!) Likewise, two different threads can call the same synchronized member function at the same time if the two threads are operating on different objects. (Your example has two different instances of SyncClass!)
The code as stands does not compile.
func5 has three open brackets followed and three close brackets
There is no close bracket to then close the class.
If you have a compiler please compile the code and post again.
I saw this on Java's synchronization tutorial:
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
The tutorial says that subsequent calls by different threads block, like so:
A: increment();
B: increment(); <-- has to wait for A to finish
...but say two threads interleave like so:
A: increment(): load c -> 0;
B: decrement(): load c -> 0;
A: increment(): increment c -> 1;
B: decrement(): decrement c -> -1;
A: increment(): save c -> 1;
B: decrement(): save c -> -1;
Finally: c == -1;
Neither has to wait, in my understanding of the tutorial; so is c protected from memory inconsistency?
Due to popular demand: the tutorial
The synchronized keyword on a (non-static) method causes the method to lock on the enclosed object - in this case the instance of SynchronizedCounter. Thus each synchronized method prevents each other synchronized method from running in another thread. So in your example, thread A's call to increment() would complete before thread B's call to decrement() would start. Therefore your class is thread safe.
Your current understanding of Java threading is not complete. In Java, every object has an "implicit lock", which is the object itself. And the "synchronized" keywords uses this implicit lock to make your code thread safe. The following code has the same effect:
public class SynchronizedCounter {
private int c = 0;
public void increment() {
synchronized(this){
c++;
}
}
public void decrement() {
synchronized(this){
c--;
}
}
public int value() {
synchronized(this){
return c;
}
}
}
Also, if you want to, you can declare multiple objects to server as simple lock objects. This, again, has the same effect:
public class SynchronizedCounter {
private int c = 0;
private Object lockObject;
public void increment() {
synchronized(lockObject){
c++;
}
}
public void decrement() {
synchronized(lockObject){
c--;
}
}
public int value() {
synchronized(lockObject){
return c;
}
}
}
Before synchronized method or synchronized block (also sometimes called guarded block) is executed, the executing thread must first obtain the lock. When it doesn't, the code in synchronized methods/block won't be executed. That's why your example will always work, because all the methods share one lock (the implicit one), none of the methods can be executed simultaneously with other methods.
For advanced locking mechanisms, please see the Lock interface.
Yes, c is protected from memory inconsistency.
However if the value of c is copied out of the object via the getter method, then that copy will live separately and become out of date.
None of the methods on SynchronizedCounter can be invoked simultaneously because they are all declared synchronised.
This does two things, firstly it creates a mutually exclusive region by requiring any thread to enter a monitor (http://en.wikipedia.org/wiki/Monitor_%28synchronization%29) and secondly it places memory barriers (http://en.wikipedia.org/wiki/Barrier_%28computer_science%29) at the entry to the method and the exit.
Thus only one thread can modify c at a time, and no matter which thread on which CPU core is executing that method then it will read the latest value of c and will make its change to c visible to the next thread that enters the monitor. For more on the memory barrier side, Doug Lea wrote a very useful guide at http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
I am trying to understand Synchornized in Java.
I understood if I have access a synchronized method on same object from 2 different Threads, only one will be able to access at a time.
But I think if the same method is being called on 2 different instances, Both Objects should be able to access the method parallel. Which would cause race condition if accessing/modifying a static member variable from the method. But I am not able to see the race condition happening in below code.
Could someone please explain whats wrong with the code or my understanding.
For reference code is accessible at : http://ideone.com/wo6h4R
class MyClass
{
public static int count=0;
public int getCount()
{
System.out.println("Inside getcount()");
return count;
}
public synchronized void incrementCount()
{
count=count+1;
}
}
class Ideone
{
public static void main(String[] args) throws InterruptedException {
final MyClass test1 = new MyClass();
final MyClass test2 = new MyClass();
Thread t1 = new Thread() {
public void run()
{
int k=0;
while (k++<50000000)
{
test1.incrementCount();
}
}
};
Thread t2 = new Thread() {
public void run()
{
int l=0;
while (l++<50000000)
{
test2.incrementCount();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
//System.out.println(t2.getState());
int x=500000000+500000000;
System.out.println(x);
System.out.println("count = " + MyClass.count);
}
}
You're right that the race condition exists. But the racy operations are so quick that they're unlikely to happen -- and the synchronized keywords are likely providing synchronization "help" that, while not required by the JLS, hide the races.
If you want to make it a bit more obvious, you can "spell out" the count = count + 1 code and put in a sleep:
public synchronized void incrementCount()
{
int tmp = count + 1;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
count=tmp;
}
That should show the races more easily. (My handling of the interrupted exception is not good for production code, btw; but it's good enough for small test apps like this.)
The lesson learned here is: race conditions can be really hard to catch through testing, so it's best to really understand the code and prove to yourself that it's right.
Since syncrhonized methods actually synchronize on this different instance methods will lock on different objects and therefore you will get race conditions since they don't block each other.
You probably have to make your own lock object and lock on that.
class MyClass
{
public static int count=0;
//this is what you lock on
private static Object lock = new Object();
public int getCount()
{
synchronized(lock){
System.out.println("Inside getcount()");
return count;
}
}
public void incrementCount()
{
synchronized(lock){
count = count+1;
}
}
//etc
Now when you run your main, this gets printed out:
1000000000
count = 100000000
Here's the relevant section of the Java specification:
"A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used."
However I fail to see where the MyClass' instances are actually incrementing "count" so what exactly are you expecting to show as a race condition?
(Taken originally from this answer)
I was reading Java Platform Performance (sadly the link seems to have disappeared from the internet since I originally posed this question) and section A.3.3 worried me.
I had been working on the assumption that a variable that dropped out of scope would no longer be considered a GC root, but this paper appears to contradict that.
Do recent JVMs, in particular Sun's 1.6.0_07 version, still have this limitation? If so, then I have a lot of code to analyse...
I ask the question because the paper is from 1999 - sometimes things change, particularly in the world of GC.
As the paper is no longer available, I'd like to paraphrase the concern. The paper implied that variables that were defined inside a method would be considered a GC root until the method exited, and not until the code block ended. Therefore setting the variable to null was necessary to permit the Object referenced to be garbage collected.
This meant that a local variable defined in a conditional block in the main() method (or similar method that contained an infinite loop) would cause a one-off memory leak unless you nulled a variable just before it dropped out of scope.
The code from the chosen answer illustrates the issue well. On the version of the JVM referenced in the document, the foo object can not be garbage collected when it drops out of scope at the end of the try block. Instead, the JVM will hold open the reference until the end of the main() method, even though it is impossible for anything to use that reference.
This appears to be the origin of the idea that nulling a variable reference would help the garbage collector out, even if the variable was just about to drop out of scope.
This code should clear it up:
public class TestInvisibleObject{
public static class PrintWhenFinalized{
private String s;
public PrintWhenFinalized(String s){
System.out.println("Constructing from "+s);
this.s = s;
}
protected void finalize() throws Throwable {
System.out.println("Finalizing from "+s);
}
}
public static void main(String[] args) {
try {
PrintWhenFinalized foo = new PrintWhenFinalized("main");
} catch (Exception e) {
// whatever
}
while (true) {
// Provoke garbage-collection by allocating lots of memory
byte[] o = new byte[1024];
}
}
}
On my machine (jdk1.6.0_05) it prints:
Constructing from main
Finalizing from main
So it looks like the problems has been fixed.
Note that using System.gc() instead of the loop does not cause the object to be collected for some reason.
The problem is still there. I tested it with Java 8 and could prove it.
You should note the following things:
The only way to force a guaranteed garbage collection is to try an allocation which ends in an OutOfMemoryError as the JVM is required to try freeing unused objects before throwing. This however does not hold if the requested amount is too large to ever succeed, i.e. excesses the address space. Trying to raise the allocation until getting an OOME is a good strategy.
The guaranteed GC described in Point 1 does not guaranty a finalization. The time when finalize() methods are invoked is not specified, they might be never called at all. So adding a finalize() method to a class might prevent its instances from being collected, so finalize is not a good choice to analyse GC behavior.
Creating another new local variable after a local variable went out of scope will reuse its place in the stack frame. In the following example, object a will be collected as its place in the stack frame is occupied by the local variable b. But b last until the end of the main method as there is no other local variable to occupy its place.
import java.lang.ref.*;
public class Test {
static final ReferenceQueue<Object> RQ=new ReferenceQueue<>();
static Reference<Object> A, B;
public static void main(String[] s) {
{
Object a=new Object();
A=new PhantomReference<>(a, RQ);
}
{
Object b=new Object();
B=new PhantomReference<>(b, RQ);
}
forceGC();
checkGC();
}
private static void forceGC() {
try {
for(int i=100000;;i+=i) {
byte[] b=new byte[i];
}
} catch(OutOfMemoryError err){ err.printStackTrace();}
}
private static void checkGC() {
for(;;) {
Reference<?> r=RQ.poll();
if(r==null) break;
if(r==A) System.out.println("Object a collected");
if(r==B) System.out.println("Object b collected");
}
}
}
The article states that:
... an efficient implementation of the
JVM is unlikely to zero the reference
when it goes out of scope
I think this happens because of situations like this:
public void doSomething() {
for(int i = 0; i < 10 ; i++) {
String s = new String("boo");
System.out.println(s);
}
}
Here, the same reference is used by the "efficient JVM" in each declaration of String s, but there will be 10 new Strings in the heap if the GC doesn't kick in.
In the article example I think that the reference to foo keeps in the stack because the "efficient JVM" thinks that is very likely that another foo object will be created and, if so, it will use the same reference. Thoughts???
public void run() {
try {
Object foo = new Object();
foo.doSomething();
} catch (Exception e) {
// whatever
}
while (true) { // do stuff } // loop forever
}
I've also performed the next test with profiling:
public class A {
public static void main(String[] args) {
A a = new A();
a.test4();
}
public void test1() {
for(int i = 0; i < 10 ; i++) {
B b = new B();
System.out.println(b.toString());
}
System.out.println("b is collected");
}
public void test2() {
try {
B b = new B();
System.out.println(b.toString());
} catch (Exception e) {
}
System.out.println("b is invisible");
}
public void test3() {
if (true) {
B b = new B();
System.out.println(b.toString());
}
System.out.println("b is invisible");
}
public void test4() {
int i = 0;
while (i < 10) {
B b = new B();
System.out.println(b.toString());
i++;
}
System.out.println("b is collected");
}
public A() {
}
class B {
public B() {
}
#Override
public String toString() {
return "I'm B.";
}
}
}
and come to the conclusions:
teste1 -> b is collected
teste2 -> b is invisible
teste3 -> b is invisible
teste4 -> b is collected
... so I think that, in loops, the JVM doesn't create invisible variables when the loop ends because it's unlikely they will be declared again outside the loop.
Any Thoughts??
Would you really have that much code to analyse? Basically I can only see this being a significant problem for very long-running methods - which are typically just the ones at the top of each thread's stack.
I wouldn't be at all surprised if it's unfixed at the moment, but I don't think it's likely to be as significant as you seem to fear.