From 0636013d65d73c682510ec04ea980d3f76d78e65 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Mon, 30 Mar 2015 18:47:07 +0200 Subject: [PATCH] Using test-and-test-and-set. See http://en.wikipedia.org/wiki/Spinlock, the section about optimizations. See also http://en.wikipedia.org/wiki/Test_and_Test-and-set. --- .../eclipse/jetty/util/thread/SpinLock.java | 31 ++++++++----------- .../jetty/util/thread/SpinLockTest.java | 13 +++----- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/SpinLock.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/SpinLock.java index d3048feba47..fc76529b64b 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/SpinLock.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/SpinLock.java @@ -20,11 +20,9 @@ package org.eclipse.jetty.util.thread; import java.util.concurrent.atomic.AtomicReference; - -/* ------------------------------------------------------------ */ -/** Spin Lock - *

This is a lock designed to protect VERY short sections of - * critical code. Threads attempting to take the lock will spin +/** + *

This is a lock designed to protect VERY short sections of + * critical code. Threads attempting to take the lock will spin * forever until the lock is available, thus it is important that * the code protected by this lock is extremely simple and non * blocking. The reason for this lock is that it prevents a thread @@ -40,32 +38,29 @@ public class SpinLock { private final AtomicReference _lock = new AtomicReference<>(null); private final Lock _unlock = new Lock(); - + public Lock lock() { - Thread thread = Thread.currentThread(); - while(true) + Thread current = Thread.currentThread(); + while (true) { - if (!_lock.compareAndSet(null,thread)) + // Using test-and-test-and-set for better performance. + Thread locker = _lock.get(); + if (locker != null || !_lock.compareAndSet(null, current)) { - if (_lock.get()==thread) + if (locker == current) throw new IllegalStateException("SpinLock is not reentrant"); continue; } return _unlock; } } - + public boolean isLocked() { - return _lock.get()!=null; + return _lock.get() != null; } - - public boolean isLockedThread() - { - return _lock.get()==Thread.currentThread(); - } - + public class Lock implements AutoCloseable { @Override diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/SpinLockTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/SpinLockTest.java index e4160f38a5a..49021091675 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/SpinLockTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/SpinLockTest.java @@ -18,17 +18,16 @@ package org.eclipse.jetty.util.thread; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Test; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + public class SpinLockTest { - @Test public void testLocked() { @@ -70,7 +69,6 @@ public class SpinLockTest assertFalse(lock.isLocked()); } - @Test public void testContend() throws Exception { @@ -121,7 +119,7 @@ public class SpinLockTest }; thread1.start(); // thread1 will be spinning here - assertFalse(held1.await(100,TimeUnit.MILLISECONDS)); + assertFalse(held1.await(100, TimeUnit.MILLISECONDS)); // Let thread0 complete hold0.countDown(); @@ -135,8 +133,5 @@ public class SpinLockTest thread1.join(); assertFalse(lock.isLocked()); - } - - }