[concurrency-interest] AtomicReferenceFieldUpdater vs Unsafe

David Holmes davidcholmes at aapt.net.au
Tue Nov 29 17:15:32 EST 2011


Nathan,

The JVM spec specifically calls out the issue of balanced/unbalanced monitor
actions aka structured locking - section 8.13. Hotspot relies on structured
locking in places, but like JRockit there are some uses (eg JVMTI raw
monitors) where balanced use can not be guaranteed and so it runs in
interpreted mode. Any bytecode manipulation tool, or alternative language
implementation using bytecodes, must be aware of JVMS 8.13 and act
accordingly.

David
  -----Original Message-----
  From: Nathan Reynolds [mailto:nathan.reynolds at oracle.com]
  Sent: Wednesday, 30 November 2011 2:55 AM
  To: dholmes at ieee.org
  Cc: David Holmes; Hanson Char; concurrency-interest
  Subject: Re: [concurrency-interest] AtomicReferenceFieldUpdater vs Unsafe


  javac will compile synchronized blocks with monitorenter and monitorexit
byte codes in the same frame.  They are always produced in a balanced
manner.  However, bytecode manipulation tools (i.e. BCEL, ASM, etc) can emit
monitorenter and monitorexit byte codes at any time.  Other languages may
(or may not) allow for unbalanced monitorenter and monitorexit.  It seems to
me that a JVM has no choice but to deal with such unbalances.

  The JRockit JVM dealt with unbalanced monitorenter and monitorexit by
executing special yet slower code.  A couple of years ago, we found a bug in
the unbalance detector which would generate false positives.  The
performance of the code was dismal until they supplied a fix.


  Nathan Reynolds | Consulting Member of Technical Staff | 602.333.9091
  Oracle PSR Engineering | Server Technology


  On 11/28/2011 9:49 PM, David Holmes wrote:
Re: Unsafe.tryMonitorEnter and Unsafe.monitorExit

So returning to the "are these truly unsafe" question the answer is: yes. At
least monitorExit is potentially unsafe.

Dave Dice reminded me (thanks Dave!) about the issue of having balanced
monitorEnter and monitorExit instructions and that monitors are always
released in the same stackframe in which they were acquired. The JVM takes
advantage of balanced monitor use to optimize locking - synchronized usage
is always balanced and JITs generate similarly balanced code, and if you mix
JVMTI locking/unlocking with synchronized then you are on your own. If you
use Unsafe.monitorExit in an unbalanced fashion then you might run into
problems.

If we were to make these a public API then we would have to account for
unbalanced use. That might mean either dropping all the optimizations that
rely on balanced use, or adding additional analysis to detect unbalanced use
and drop back to interpreted code in such cases. Either way that is a lot of
work (not to mention the timeout support) to accommodate an uncommon need
already satisfiable through Unsafe - in my opinion of course.

Cheers,
David


Hanson Char writes:
Sorry I meant Unsafe#tryMonitorEnter and #monitorExit.  (I realized
the mistake after sending out the email, but thought the context would
self recover/make it clear :))

Can you expand on this.
One practical (and critical) case I've come across is that under some
extreme circumstances , a 3rd party database connection pool would get
into a "stuck" state.  Doesn't happen often but it does happen.  When
it did, any attempt to inspect the respective pool via JMX calling the
getter methods for info such as the number of active/idle connections
would cause the inspecting thread to get stuck.

Looking into the code (of the third party library) it was clearly
related to the use of synchronized methods, including the getter
methods for the stats.

Via Unsafe#tryMonitorEnter, the application was able to get some
information out of the pool, and initiate some emergent recovery
actions such as interrupting the blocked threads, resetting the db
connection pool and jdbc driver, or even just generating alerts/alarms
to the support staff.

This also allows the application to avoid piling up threads getting
sucked into a black hole which would lead to the eventual death of the
JVM (ie requiring a restart).

 >There's no such proposal on the table at the moment. A tryLock without a
timed-variant is of limited use and monitors don't currently support
timed-acquisition, so there would be a bit of VM work to do -
particularly
if you wanted it intrinisfied by the compilers.
Indeed that's what I guessed was the reason (of why these two methods
are hidden behind Unsafe).  But isn't limited use better than nothing
in this case ?  It seems clearly I am not alone:

  http://www.javaspecialists.eu/archive/Issue194.html

It appears the use of this tryMonitorEnter is the only way we (or just
I) can guarantee the application to retain liveness in accessing third
party library in face of invoking (3rd party owned) synchronized
methods.  As long as there is liveness, the application can do
something about it and therefore allow such synchronized problems to
be limited to a partial failure that can be recovered.  The use could
be limited, but important.

I don't know if, however, the tryMonitorEnter/monitorExit method is
truly "unsafe" in the sense that if calling them may cause the JVM to
crash ?  If not, these methods should probably be re-located to a more
sensible class anyway, like perhaps Object ?

Regards,
Hanson

On Sun, Nov 27, 2011 at 8:23 PM, David Holmes
<davidcholmes at aapt.net.au> wrote:
Hanson Char writes:
Performance aside, I find the use of Unsafe#tryMonitor{Enter,Exit}
tryExit ???

extremely valuable in face of legacy code that uses synchronized
block/method but the caller cannot afford to be "trapped" when calling
the legacy code even when it entered into a indefinitely blocking
state (within the synchronized block/method).
Can you expand on this. The only use case I can see is if you know the
legacy code will synchronize on a given instance and so you
acquire it first
using tryLock. But that only protects you from the initial monitor
acquisition blocking indefinitely. This seems of very limited
applicability.
It would be really nice if the tryMonitor{Enter,Exit} can be promoted
into a normal and safe jdk class for general use, so we don't need to
use it in stealth mode.  Or maybe it already is in Java 7+ ?
There's no such proposal on the table at the moment. A tryLock without a
timed-variant is of limited use and monitors don't currently support
timed-acquisition, so there would be a bit of VM work to do -
particularly
if you wanted it intrinisfied by the compilers.

Cheers,
David Holmes

Regards,
Hanson

On Thu, Nov 17, 2011 at 3:26 AM, Roman Elizarov
<elizarov at devexperts.com> wrote:
Unfortunately, I had to use Unsafe myself from time to time just for
performance reasons (because I have to write a lot of
high-performance
code).



/Roman



From: Dr Heinz M. Kabutz [mailto:heinz at javaspecialists.eu]
Sent: Thursday, November 17, 2011 3:01 PM
To: Roman Elizarov
Cc: Martin Buchholz; concurrency-interest

Subject: Re: [concurrency-interest] AtomicReferenceFieldUpdater
vs Unsafe


My thoughts exactly, Roman.  Us mere mortals figure out the
"how to" by
reading JDK source code and when we see Unsafe being used, we
go: "Ah, now
that's a good class to use..." ;-)

>From my newsletter:
http://www.javaspecialists.eu/archive/Issue194.html
"In a recent email, one of my youngest readers, 17 year old Mr
S.Perlov from
the Ukraine, suggested that I tell you about the class
sun.misc.Unsafe. Up
to now I have avoided writing about it, as it is a class
that should be
avoided. Here are two reasons: #1 it is "unsafe" and lets us
do all the
nasty things that we had in C, such as pointer arithmetic or
modifying
memory directly. #2 it is a sun.misc.* class. You do not
know when that
might be renamed to oracle.misc.Unsafe or whether you will
even run your
program on a Sun JVM. By binding yourself to a specific
implementation of
the JVM, you are limiting the application of your code.

Two reasons to not use Unsafe. I have personally never used Unsafe in
production code. Some experts do use it to write directly to memory.
Dangerous stuff! "

Regards



Heinz

--

Dr Heinz M. Kabutz (PhD CompSci)

Author of "The Java(tm) Specialists' Newsletter"

Sun Java Champion

IEEE Certified Software Development Professional

http://www.javaspecialists.eu

Tel: +30 69 72 850 460

Skype: kabutz

On 11/17/11 12:53 PM, Roman Elizarov wrote:

The downside is that it fuels the use of sun.misc.Unsafe by 3rd party
programmer. Every day there are more and more blogs explaining
advantages of
Unsafe to the average programmer. I’ve just recently reposted
one of those
for the Russian programmers community.



Are there any concrete plans (say for Java 8) to bring the
performance of
**Updater classes on par with Unsafe (maybe by improving
HotSpot, so that it
can eliminate all the extra checks and compile **Updater
method into the
same code as produced by direct use of Unsafe)? Shall we
continue to rely on
Unsafe for Java 8 and beyond or get ready for its eventual
elimination from
our codebase?



Sincerely,

Roman Elizarov



From: concurrency-interest-bounces at cs.oswego.edu
[mailto:concurrency-interest-bounces at cs.oswego.edu] On
Behalf Of Martin
Buchholz
Sent: Thursday, November 17, 2011 3:45 AM
To: Dr Heinz M. Kabutz
Cc: concurrency-interest
Subject: Re: [concurrency-interest] AtomicReferenceFieldUpdater
vs Unsafe




On Wed, Nov 16, 2011 at 13:37, Dr Heinz M. Kabutz
<heinz at javaspecialists.eu>
wrote:

In Java 6, classes like ConcurrentLinkedQueue and
SynchronousQueue used the
AtomicReferenceFieldUpdater to update the next, head, etc. fields.

In Java 7, this was changed to instead use
Unsafe.compareAndSwapObject()
directly.

The AtomicReferenceFieldUpdater does a bunch of error checking
every time it
is called, like this:

          if (obj == null || obj.getClass() != tclass || cclass
!= null ||
              (update != null && vclass != null &&
               vclass != update.getClass()))
              updateCheck(obj, update);
          return unsafe.compareAndSwapObject(obj, offset,
expect, update);
My thinking is that the programmers changing
ConcurrentLinkedQueue et al
probably wanted to improve the performance by not having to
do all that
checking every time it is called.  The
Unsafe.compareAndSwapObject() method
is probably compiled to a single CPU instruction.

Is that correct?

Yes.



Is there any other reason for this change?

The previous way was more principled, in the manner of "eat your own
dogfood".  Maybe we've become just a tiny bit less principled.

_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu
http://cs.oswego.edu/mailman/listinfo/concurrency-interest



_______________________________________________
Concurrency-interest mailing list
Concurrency-interest at cs.oswego.edu
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20111130/7682a5d0/attachment-0001.html>


More information about the Concurrency-interest mailing list