Forum Controls
Spotlight Features

The Rich Engineering Heritage Behind Dependency Injection

Andrew McVeigh takes us on a tour of the rich heritage behind dependency injection, what it represents, and tells us why its here to stay.

NetBeans 6: Matisse Updates

NetBeans 6 delivers great updates to the Matisse GUI builder. Spend a few minutes with Roman Strobl and get an expert briefing on what's new and what has changed.

Introduction to Groovy Part 3

In this, the third and final installation of Andres' Introduction to Groovy series, you learn about how Groovy handles variable numbers of arguments, named parameters, currying, and more about Groovy operators. Including, some new operators.

Easier Custom Components with Swing Fuse

Swing Fuse (actually just Fuse), is a framework designed to make it easier to create your own custom desktop components. In this article, Daniel Spiewak shows you how to get started and provides sample source code you can download.

Benchmark Analysis: Guice vs Spring

Willam Louth shows how he uses JXInsight Probes to investigate probable performance issues with code bases that he is not familiar with. He also highlights possible pitfalls in creating a benchmark, as well as in the analysis of results.
Replies: 15 - Pages: 2   [ 1 2 | Next ]
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

The Death of "synchronized"?

At 11:02 AM on Sep 13, 2007, Daniel Spiewak wrote:

Java 5 made numerous changes to various aspects of "Java". In fact, it was probably the biggest update Java has ever made, bringing dozens of new language syntax features, compiler enhancements, and scores of new APIs. In the wake of all these large changes (enums, generics, annotations), we tend to forget about the smaller API additions and how they effect our development. A prime example of this are the concurrency libs.

Java 5 introduced a number of new mechanisms which make threading and locking quite a bit easier. Perhaps the most important of these is ReadWriteLock. Since the release of Java 5, I've started to see more and more code that looks like this:
public void foo() {
    lock.writeLock().lock();
    try {
        bar = "Bad news";
    } finally {
        lock.writeLock().unlock();
    }
}

This is an increasingly common pattern as more and more developers either recognize the power of ReadWriteLock over traditional synchronization, or are allowed by their company to switch to Java 5 specific APIs. It's really hard to argue with this code and it's capabilities. ReadWriteLock(s) provide the flexibility to not only lock in one method and unlock in another, but also have both exclusive and inclusive locking, allowing for greater concurrency and performance.

The interesting thing that I'm beginning to see is that ReadWriteLock is rising in usage completely at the expense of older mechanisms for locking such as synchronized and volatile. For example, the sample above used to be written like this:
public synchronized void foo() {
    bar = "Bad news";
}

Or even like this:
public void foo() {
    synchronized (bar) {
        bar = "Bad news";
    }
}

This style may be a lot less flexible, but it's no less valid. Also, it happens to be less verbose; and for a lot of use cases this is sufficient. Think of how many times you've written a singleton. Is it really necessary to make it thread-safe with a static ReadWriteLock or is synchronizing the method sufficient?

With companies on a "one release behind" policy switching to Java 5, these questions are of rising importance. Design patterns specific to the new features are becoming more dominant, and best practice needs to be defined. Should the use of synchronized be deprecated altogether, or is it still a valid part of the language with valid use-cases? Are there times where ReadWriteLock is just plain overkill? On the flip side of things, what are the performance implications? Is ReadWriteLock used in exclusively exclusive mode that much more performant than synchronized?
1 . At 11:24 AM on Sep 13, 2007, Chris Sargent wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

Anecdotally I believe just about all the 'new' concurrency features in util.concurrent are more performant than using the 'old' style synchronization, volatile, etc. Whether this is actually the case I don't know - there aren't many (any?) benchmarks I can find.

Like most design/implementation decisions it's a case of horses for courses - if you really must have high performance then the new concurrency features seem logical, if not then certainly the traditional style is less verbose and therefore clearer and more maintainable.
"It is impossible to make anything foolproof, because fools are so ingenious."
2 . At 11:38 AM on Sep 13, 2007, Christoph Kutzinski wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

> Anecdotally I believe just about all the 'new'
> concurrency features in util.concurrent are more
> performant than using the 'old' style
> synchronization, volatile, etc. Whether this is
> actually the case I don't know - there aren't many
> (any?) benchmarks I can find.

I remember seeing a benchmark (don't find the URL right now), which said that the new locks are faster than the old "synchronized"-locks in Java 5. However with Java 6 the gap almost closed, so there were nearly no differences between both.


On the question if "synchronized" should be deprecated altogether:
I don't think so. Why would we deprecate something which has been proven to work for so many years now. More importantly synchronized is fool-proof: it's easy to forget the finally block to unlock a new ReadWriteLock. With synchronized this can never happen.
3 . At 11:40 AM on Sep 13, 2007, Chris Kent wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

According to "Java Concurrency in Practice" ReentrantLock does perform better than synchronization under Java 5 but in Java 6 there's virtually no difference (presumably he's talking about Sun's VM).
4 . At 12:07 PM on Sep 13, 2007, Mike P wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

Given that Java 1.6's synchronizing is as good as using Locks, imagine if 'synchronized' would be a new upcoming feature in Java 1.7. We'd all look forward to being able to strip out all those finally blocks and verbal statements, and replace them with the more safer and elegant looking synchronized statements...
5 . At 12:30 PM on Sep 13, 2007, Genady Beryozkin wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

> Given that Java 1.6's synchronizing is as good as
> using Locks, imagine if 'synchronized' would be a new
> upcoming feature in Java 1.7. We'd all look forward
> to being able to strip out all those finally blocks
> and verbal statements, and replace them with the more
> safer and elegant looking synchronized statements...

:)

I think that first there were locks and then arrived the monitors. Since the OS usually doesn't implement monitors, people who had to write plain C code will like plain locks more than the synchronized statement.
Genady Beryozkin
Get the RMI Plugin for Eclipse
6 . At 4:25 PM on Sep 13, 2007, Artur Biesiadowski DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

RRWLock in Java6 + lots of threads = memory gone

Unfortunately, in Java 6 ReentrantReadWriteLock implementation has changed, so every lock has it's own ThreadLocal now. In our system, we have millions of locks, each accessible from hundreds of threads - with default implementation, our memory usage almost doubled because of the locks alone.

You can see my report at
http://forum.java.sun.com/thread.jspa?threadID=5114887

To be able to use Java 6, we had to copy/paste Java 5 implementation of the locks in application package and use it, instead of default one.

If you are using limited number of locks, or you have high thread-to-object affinity, problem is probably not going to hit you. Unfortunately, in our system, we have thread pools everywhere, so ThreadLocal memory usage explode quite heavily for locks.
7 . At 5:49 PM on Sep 13, 2007, Clemens Eisserer DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

Re: RRWLock in Java6 + lots of threads = memory gone

Well it seems your use of RRWLocks is a real corner-case, so although the RRWLock implementation in Java6 is maybe better for 99.95% of all users you are one of the 0.01% that has been hit really hard.

I wonder wether this design is really that good. Locks may or may not be lightweight objects (they could be e.g. associated with OS datastructures in some implementations) and in fact your program relies heavily on the way they are implemented.
I would understand your anger if you would stumble over problems with thousands of locks, but millions of them?
I cannot even recommend using synchronized, which also uses OS datastructures when contended (at least for Sun
's JVM) - so memory useage may be smaller first but grow with contention.

However great you've found a solution to the problem which fits your needs (although its not allowed by Sun, so I would not talk that "open" about it).

lg Clemens
8 . At 7:51 PM on Sep 13, 2007, Ben Loud wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

> Anecdotally I believe just about all the 'new'
> concurrency features in util.concurrent are more
> performant than using the 'old' style
> synchronization, volatile, etc.

Actually I believe it's the other way round. See this post from HotSpot engineer Dave Dice:

http://blogs.sun.com/dave/entry/java_util_concurrent_reentrantlock_vs

"The builtin synchronized construct currently has a few advantages, such as lock coarsening, biased locking and the potential for lock elision via escape analysis. Those optimizations aren't currently implemented for ReentrantLock and friends."
9 . At 7:56 PM on Sep 13, 2007, Neil Bartlett wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

No! "Synchronized" should not be deprecated, it's a crucial part of the Java memory model. In fact I believe your first code example is broken, unless the bar field is declared as volatile. The reason is that the change to the value of the field is not necessarily visible to another thread unless both the read and write to bar are synchronized on the same monitor. The RW lock serves to sequence the operations correctly, but we might still get the old value of the field when we read it, despite the fact that the read happens after the write!

Java 5's concurrency library introduced some very useful abstractions, but they do not replace synchronized. However, they DO make it absolutely unnecessary to use wait() and notify()/notifyAll() in normal code.
10 . At 8:13 PM on Sep 13, 2007, Osvaldo Doederlein wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

> No! "Synchronized" should not be deprecated, it's a
> crucial part of the Java memory model. In fact I
> believe your first code example is broken, unless the
> bar field is declared as volatile. The reason is that
> the change to the value of the field is not
> necessarily visible to another thread unless both the
> read and write to bar are synchronized on the same
> monitor.

Not true - locks have the same JMM semantics of monitors; if all threads that access 'bar' are guarded by lock()/unlock() operations on the same Lock, they're safe wrt visibility of updates.
11 . At 8:39 PM on Sep 13, 2007, Neil Bartlett wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

> Not true - locks have the same JMM semantics of
> monitors; if all threads that access 'bar' are
> guarded by lock()/unlock() operations on the same
> Lock, they're safe wrt visibility of updates.

Yes indeed, you're right. I think I overreacted a little to the suggestion of removing or deprecating the synchronized keyword!

I would still say that synchronized should be the first mechanism to use, thanks to its mature semantics and the impossibility of forgetting to release the monitor. ReadWriteLock is an optimisation that should be used in the event that profiling reveals poor concurrency in a particular segment of code.
12 . At 12:37 AM on Sep 14, 2007, Ondrej Hurt wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

Sigh, this idea of getting rid of synchronized in favor of writing lock-try-finally-unlock ad nauseum could really originate only in Java programmer's head because they are used to this kind of copy and paste code. But I believe that you could really replace synchronize with closures in Java 7. Javascript example:

function synchronized(lock, func) {
lock.lock();
try {
func();
} finally {
lock.unlock();
}
}

synchronized(someObject, function () { someCode...; });


The syntax is not ideal but I hope that Java 7 will come with something less verbose. And of course you could easily write synchronized for read-write locks:

function synchronizedReading(RWLock, func) {
RWLock.lockForReading();
try {
func();
} finally {
RWLock.unlock();
}
}
13 . At 1:05 AM on Sep 14, 2007, Tim Boudreau DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

Re: The Death of "synchronized"?

Is there really a significant difference between

public void foo() {
lock.writeLock().lock();
try {
bar = "Bad news";
} finally {
lock.writeLock().unlock();
}
}

and

Object lock = new Object();
public void foo() {
synchronized (lock) {
doSomething();
}
}

and the above example? It seems to me that we're talking more about something that assists one's mental conception of "there is a lock here" by requiring explicit code that's likely to make one aware of what the code artifact is doing - but either one adds up to the same thing, and somewhere in there is going to be doing the same thing. Objects are a convenience for human beings, and code should make such constructs as explicit and understandable as possible - and "synchronized" requires more mental analysis than a more explicit locking construct - so I think this is goodness.


Locks that allow many threads to concurrently read but make writes atomic - making that trivial seems like what's really interesting - creating critical sections is easy.

Tim Boudreau
NetBeans.org
Evangelist/Senior Staff Engineer, Sun Microsystems
14 . At 5:44 AM on Sep 14, 2007, Artur Biesiadowski DeveloperZone Top 100 wrote:
  Click to reply to this thread Reply

Re: RRWLock in Java6 + lots of threads = memory gone

> I wonder wether this design is really that good.
> Locks may or may not be lightweight objects (they
> could be e.g. associated with OS datastructures in
> some implementations) and in fact your program relies
> heavily on the way they are implemented.

Yes, of course. Same way, my program depends on the fact if java.lang.Double takes n bytes or n KILObytes. Any 3 orders of magnitude change in implementation is going to affect the program relying on particular aspect.

Anyway, I'm not dependent on the way in which lock contention is resolved. I can accept various implementations of that, with various costs. On the other hand, I don't think that any other implementation has a lock with a cost equal to number of threads which used it in the past... My locks are mostly not contended, with 2-3 levels of recursion from same thread max.

I agree that most programs are using a lot smaller number of locks, so they are not affected much. If you are unlucky enough to be in that 0.01% hit by that, simple upgrade to java 6 can completely break you app.

thread.rss_message