Locking on local variables

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Locking on local variables

Sleiman Jneidi
Hi everyone, 

From what I know, locking on local variables is useless, Brian Goetz in his book gave the following as an example of a bad lock

 synchronized(new Object()){
  ..
 }

So I assume, the code above is equivalent to the following

  Object o = new Object();
  
 synchronized(o){
  ..
 }

However looking at ConcurrentHashMap#computeIfAbsent I see the following

Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
    ...
    }

Just curious, why is that?


Thanks
Sleiman 


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Dmitry Zaslavsky
Object o = new Object();
synchronized(o){
  
}

The reason this code looks incorrect is that 'o' is not shared and not known to any other thread.
Therefore you can't possibly be achieving any synchronization with any other thread.

Consider slightly modified example

// Not local (outside of your function)
volatile Object lock = null;

// Local code
Object o = new Object();
synchronized(o){
  lock = o;
}

While this code has some other issues. At least it's potentially meaningful. It will acquire the lock on 'o' and will publish it to the outside world
Now some other thread can find and synchronize on it

Look at the next line in computeIfAbsent
It publishes that lock 'r' in casTabAt()   


On Fri, Jan 15, 2016 at 10:21 AM, Sleiman Jneidi <[hidden email]> wrote:
Hi everyone, 

From what I know, locking on local variables is useless, Brian Goetz in his book gave the following as an example of a bad lock

 synchronized(new Object()){
  ..
 }

So I assume, the code above is equivalent to the following

  Object o = new Object();
  
 synchronized(o){
  ..
 }

However looking at ConcurrentHashMap#computeIfAbsent I see the following

Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
    ...
    }

Just curious, why is that?


Thanks
Sleiman 


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Vitaly Davidovich
In reply to this post by Sleiman Jneidi
Looks like `r` is entered into the table within that synchronized block, meaning it's potentially visible to other threads.  Holding its monitor precludes other threads from observing state (as other threads will attempt to acquire the monitor on it) until the initial insertion is complete (I'm sure Doug can give a more thorough explanation).

On Fri, Jan 15, 2016 at 10:21 AM, Sleiman Jneidi <[hidden email]> wrote:
Hi everyone, 

From what I know, locking on local variables is useless, Brian Goetz in his book gave the following as an example of a bad lock

 synchronized(new Object()){
  ..
 }

So I assume, the code above is equivalent to the following

  Object o = new Object();
  
 synchronized(o){
  ..
 }

However looking at ConcurrentHashMap#computeIfAbsent I see the following

Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
    ...
    }

Just curious, why is that?


Thanks
Sleiman 


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Vitaly Davidovich
All that to say `r` is not a local in the sense Brian's book intended; the book ought to have called this a temporary, not a local.  But perhaps a better description still is "thread local" (or "non-escaping" with escape referring to sharing between threads, etc).

On Fri, Jan 15, 2016 at 10:58 AM, Vitaly Davidovich <[hidden email]> wrote:
Looks like `r` is entered into the table within that synchronized block, meaning it's potentially visible to other threads.  Holding its monitor precludes other threads from observing state (as other threads will attempt to acquire the monitor on it) until the initial insertion is complete (I'm sure Doug can give a more thorough explanation).

On Fri, Jan 15, 2016 at 10:21 AM, Sleiman Jneidi <[hidden email]> wrote:
Hi everyone, 

From what I know, locking on local variables is useless, Brian Goetz in his book gave the following as an example of a bad lock

 synchronized(new Object()){
  ..
 }

So I assume, the code above is equivalent to the following

  Object o = new Object();
  
 synchronized(o){
  ..
 }

However looking at ConcurrentHashMap#computeIfAbsent I see the following

Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
    ...
    }

Just curious, why is that?


Thanks
Sleiman 


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest




_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Godmar Back
In reply to this post by Sleiman Jneidi

r is not a local variable (in the sense that it doesn't escape), you missed:

               Node<K,V> r = new ReservationNode<K,V>();
                synchronized (r) {
                    if (casTabAt(tab, i, null, r)) {



On Fri, Jan 15, 2016 at 10:21 AM, Sleiman Jneidi <[hidden email]> wrote:
Hi everyone, 

From what I know, locking on local variables is useless, Brian Goetz in his book gave the following as an example of a bad lock

 synchronized(new Object()){
  ..
 }

So I assume, the code above is equivalent to the following

  Object o = new Object();
  
 synchronized(o){
  ..
 }

However looking at ConcurrentHashMap#computeIfAbsent I see the following

Node<K,V> r = new ReservationNode<K,V>();
    synchronized (r) {
    ...
    }

Just curious, why is that?


Thanks
Sleiman 


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

thurstonn
In reply to this post by Sleiman Jneidi
Just curious, is this something the JIT optimizes?
It is provable that the lock will be uncontended at the point of monitorenter; on the other hand, it's an unusual pattern so probably low priority among all things that could be optimized
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Aaron Grunthal
That's part of escape analysis.

http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis

On 15.01.2016 20:20, thurstonn wrote:

> Just curious, is this something the JIT optimizes?
> It is provable that the lock will be uncontended at the point of
> monitorenter; on the other hand, it's an unusual pattern so probably low
> priority among all things that could be optimized
>
>
>
> --
> View this message in context: http://jsr166-concurrency.10961.n7.nabble.com/Locking-on-local-variables-tp13183p13188.html
> Sent from the JSR166 Concurrency mailing list archive at Nabble.com.
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Martin Buchholz-3
In reply to this post by Sleiman Jneidi
On Fri, Jan 15, 2016 at 7:21 AM, Sleiman Jneidi
<[hidden email]> wrote:

> From what I know, locking on local variables is useless

The key observation is that you can't synchronize on variables, only on objects.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Vitaly Davidovich
In reply to this post by thurstonn
What type of optimization are you thinking of? The lock needs to be acquired and held for the duration since the object escapes almost immediately there.

On Friday, January 15, 2016, thurstonn <[hidden email]> wrote:
Just curious, is this something the JIT optimizes?
It is provable that the lock will be uncontended at the point of
monitorenter; on the other hand, it's an unusual pattern so probably low
priority among all things that could be optimized



--
View this message in context: http://jsr166-concurrency.10961.n7.nabble.com/Locking-on-local-variables-tp13183p13188.html
Sent from the JSR166 Concurrency mailing list archive at Nabble.com.
_______________________________________________
Concurrency-interest mailing list
<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;Concurrency-interest@cs.oswego.edu&#39;)">Concurrency-interest@...
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


--
Sent from my phone

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Martin Buchholz-3
In reply to this post by Aaron Grunthal
On Fri, Jan 15, 2016 at 1:32 PM, Aaron Grunthal
<[hidden email]> wrote:
> That's part of escape analysis.
>
> http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis

In this case the object does escape, but we can optimize operations
that occur while the object is provably thread-confined.  When we
implement synchronizers in Java, we often hand-optimize by using e.g.
Unsafe.putInt on volatile fields before publication.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Vitaly Davidovich
You need a control flow sensitive EA pass, which Hotspot doesn't have (graal does though), to even enable such optimization from compiler.  Not sure cost/benefit is in favor of this since hand rolling such things is pretty easy.

On Friday, January 15, 2016, Martin Buchholz <[hidden email]> wrote:
On Fri, Jan 15, 2016 at 1:32 PM, Aaron Grunthal
<<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;aaron.grunthal@infinite-source.de&#39;)">aaron.grunthal@...> wrote:
> That's part of escape analysis.
>
> http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis

In this case the object does escape, but we can optimize operations
that occur while the object is provably thread-confined.  When we
implement synchronizers in Java, we often hand-optimize by using e.g.
Unsafe.putInt on volatile fields before publication.
_______________________________________________
Concurrency-interest mailing list
<a href="javascript:;" onclick="_e(event, &#39;cvml&#39;, &#39;Concurrency-interest@cs.oswego.edu&#39;)">Concurrency-interest@...
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


--
Sent from my phone

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

thurstonn
In reply to this post by Vitaly Davidovich
Vitaly Davidovich wrote
What type of optimization are you thinking of? The lock needs to be
acquired and held for the duration since the object escapes almost
immediately there.
As I wrote, the  optimization would follow from the observation that the monitor is provably uncontended.
Presumably, optimization would be something along the lines of a volatile write vis a vis a CAS.

Now, there's already been a great deal of effort put into JVMs to make uncontended monitor acquisition cheap (biased, lightweight monitors), so it's already fairly cheap
Reply | Threaded
Open this post in threaded view
|

Re: Locking on local variables

Mohan Radhakrishnan
I understand that there is a switch to enable biased locking. What are lightweight monitors ? Thin locks/fat locks ?

Thanks,
Mohan

On 17 January 2016 at 20:26, thurstonn <[hidden email]> wrote:
Vitaly Davidovich wrote
> What type of optimization are you thinking of? The lock needs to be
> acquired and held for the duration since the object escapes almost
> immediately there.

As I wrote, the  optimization would follow from the observation that the
monitor is provably uncontended.
Presumably, optimization would be something along the lines of a volatile
write vis a vis a CAS.

Now, there's already been a great deal of effort put into JVMs to make
uncontended monitor acquisition cheap (biased, lightweight monitors), so
it's already fairly cheap



--
View this message in context: http://jsr166-concurrency.10961.n7.nabble.com/Locking-on-local-variables-tp13183p13194.html
Sent from the JSR166 Concurrency mailing list archive at Nabble.com.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest