Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Synchronization constructs in Java and their implications

26 views
Skip to first unread message

Minkoo Seo

unread,
Sep 26, 2005, 7:44:54 AM9/26/05
to
Hi, all.

I'm not sure whether this is the already discussed issue or not.
Anyway, searching 'JAVA', 'JAVA spinlock', and 'JAVA reentrantlock'
didn't return any articles seems to be relevant to my question.

Here's my question. As some of you might already knows,
JDK 5.0 added some new synchronization constructs like
ReentrantLock, Semaphore, and AtomicInteger. Before
them, 'synchronized' was the only keyword available. And it
automatically inserts memory barrier which make it possible to
thread-safe programs in SMP. However, it is not obvious whether
those new constructs are thread safe or not. So, please tell me.
Are those constructs insert memory barriers as the synchronized
keyword does?

For your information, I post a code snippet which gets locks using
several
ways:

// lock approach
private ReentrantLock lock = new ReentrantLock();
public void lock_method(int n) {

try { startSignal.await(); } catch(InterruptedException ie) {
ie.printStackTrace(); }
lock.lock();
try {
System.out.println(dummy + "+" + n + "=" + (dummy+n));
dummy++;
}
finally {
lock.unlock();
}
}

// semaphore approach
private Semaphore s = new Semaphore(1);
public void semaphore_method(int n) {

try { startSignal.await(); } catch(InterruptedException ie) {
ie.printStackTrace(); }

try {
s.acquire();
System.out.println(dummy + "+" + n + "=" + (dummy+n));
dummy++;
}
catch(InterruptedException ie) {
ie.printStackTrace();
}
finally {
s.release();
}
}

// spin lock approach
// to get dummy value from memory, we need to make it atomic
AtomicInteger ai_dummy;
public void spin_lock(int n) {

int local_dummy = ai_dummy.getAndIncrement();

System.out.println(local_dummy + "+" + n + "=" + (local_dummy +
n));
}

Joe Seigh

unread,
Sep 26, 2005, 7:57:50 AM9/26/05
to
Minkoo Seo wrote:
> Hi, all.
>
> I'm not sure whether this is the already discussed issue or not.
> Anyway, searching 'JAVA', 'JAVA spinlock', and 'JAVA reentrantlock'
> didn't return any articles seems to be relevant to my question.
>
> Here's my question. As some of you might already knows,
> JDK 5.0 added some new synchronization constructs like
> ReentrantLock, Semaphore, and AtomicInteger. Before
> them, 'synchronized' was the only keyword available. And it
> automatically inserts memory barrier which make it possible to
> thread-safe programs in SMP. However, it is not obvious whether
> those new constructs are thread safe or not. So, please tell me.
> Are those constructs insert memory barriers as the synchronized
> keyword does?

Yes. They're using a combination of synchronized/notify/wait, the
new interlocked atomics, and JSR-133 volatiles which have
acquire/release semantics, so everything should be ok in theory.

--
Joe Seigh

When you get lemons, you make lemonade.
When you get hardware, you make software.

Minkoo Seo

unread,
Sep 26, 2005, 8:06:22 AM9/26/05
to
I've timed an example program in which 1,000 threads competed for
one lock using the codes posted.

According to my results, synchronized keyword was the slowest one:
Synchornized: 1139.4 ms
Lock: 817.7 ms
Semaphore: 823.8 ms
Spinlock: 1.1 ms

Accordingly, it does not make sense that all those constructs use
synchronized keyword internally, doesn't it?

Joe Seigh

unread,
Sep 26, 2005, 8:17:02 AM9/26/05
to

Not on the fast path parts anyway which are probably using lock-free
logic.

Minkoo Seo

unread,
Sep 26, 2005, 8:23:58 AM9/26/05
to
Firstly, I'd like to thank you for your reply. Please, let me leave
'Spinlock' case out. I made a mistake regarding the spin lock
construct. Anyway, I still have questions about the other constructs.
Following is the code to get a lock using synchronized/Semaphore/Re-
entrantLock:

// old synchornized keyword
public void synchornized_method(int n) {

try { startSignal.await(); } catch(InterruptedException ie) {
ie.printStackTrace(); }

synchronized(this) {

To me, all three seem to try to get a lock in a quite similar
fashion. But, their performance are different. What's the reason?
Could you elaborate?

Sincerely,
Minkoo Seo.

Joe Seigh

unread,
Sep 26, 2005, 8:50:18 AM9/26/05
to
Minkoo Seo wrote:
> Firstly, I'd like to thank you for your reply. Please, let me leave
> 'Spinlock' case out. I made a mistake regarding the spin lock
> construct. Anyway, I still have questions about the other constructs.
> Following is the code to get a lock using synchronized/Semaphore/Re-
> entrantLock:
[...]

> To me, all three seem to try to get a lock in a quite similar
> fashion. But, their performance are different. What's the reason?
> Could you elaborate?
>

You need to look at the source for those constructs. They're
probably using the interlocked compare and swap methods from
the JSR-166 Atomic stuff to implement a lock. It's possible that
compare and swap is faster than the monitorenter instruction for
uncontended lock acquisition, though I'd be surprised if that was
the case given the performance sensitivity of monitorenter.

David Holmes

unread,
Oct 3, 2005, 3:31:30 AM10/3/05
to
"Minkoo Seo" <minko...@gmail.com> wrote in message
news:1127735094....@g43g2000cwa.googlegroups.com...

> Here's my question. As some of you might already knows,
> JDK 5.0 added some new synchronization constructs like
> ReentrantLock, Semaphore, and AtomicInteger. Before
> them, 'synchronized' was the only keyword available. And it
> automatically inserts memory barrier which make it possible to
> thread-safe programs in SMP. However, it is not obvious whether
> those new constructs are thread safe or not. So, please tell me.
> Are those constructs insert memory barriers as the synchronized
> keyword does?

For Lock implementations like ReentrantLock the memory semantics are clearly
documented: see the heading "Memory Synchronization" in the Lock javadocs.
All Lock implementations must behave in a simila fashion to monitor
acquisition and release.

For Atomics the memory synchronization semantics are documented on the
package.html page for java.util.concurrent.atomic. Basically atomic
variables act like volatile variables.

For synchronizers like Semaphore the memory semantics are not currently
documented, but will be in Java 6. Basically "acquire" operations like
Semaphore.acquire have acquire semantics, and release operations like
Semaphore.release have release semantics.

The j.u.c classes are not built on-top of the built-in language
synchronization features - like synchronized methods, or use of
Object.wait()/notify(). Atomics are intrinsified by the VM (for the basic
atomic classes); the lock implementations are built on top of atomics, and
use of the LockSupport.park/unpark API for blocking; other classes are then
built on top of locks and/or use atomics themselves. Most of the
synchronizer classes build on AbstractQueuedSynchronizer which uses atomics
and LockSupport.

The built-in synchronized mechanism generally (pre Java 6 anyway) performs
better in the uncontended case as a lot of effort has gone into making
uncontended synchronization as cheap as possible in the VM. However,
implementations like ReentrantLock perform much better under contention. A
Semaphore used as a mutual exclusion lock should perform similarly to
ReentrantLock - or marginally better as it is built from the same mechanism
but doesn't have to support reentrant acquisition.

You generally don't find a lot of good information about Java concurrency in
comp.programming.threads. If you are really interested then look at the
concurrency-interest mailing list:
http://gee.cs.oswego.edu/dl/concurrency-interest/

David Holmes


0 new messages