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.
This commit is contained in:
Simone Bordet 2015-03-30 18:47:07 +02:00
parent d3786262af
commit 0636013d65
2 changed files with 17 additions and 27 deletions

View File

@ -20,9 +20,7 @@ package org.eclipse.jetty.util.thread;
import java.util.concurrent.atomic.AtomicReference;
/* ------------------------------------------------------------ */
/** Spin Lock
/**
* <p>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
@ -43,12 +41,14 @@ public class SpinLock
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;
}
@ -58,12 +58,7 @@ public class SpinLock
public boolean isLocked()
{
return _lock.get()!=null;
}
public boolean isLockedThread()
{
return _lock.get()==Thread.currentThread();
return _lock.get() != null;
}
public class Lock implements AutoCloseable

View File

@ -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());
}
}