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:
parent
d3786262af
commit
0636013d65
|
@ -20,9 +20,7 @@ package org.eclipse.jetty.util.thread;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Spin Lock
|
|
||||||
* <p>This is a lock designed to protect VERY short sections of
|
* <p>This is a lock designed to protect VERY short sections of
|
||||||
* critical code. Threads attempting to take the lock will spin
|
* critical code. Threads attempting to take the lock will spin
|
||||||
* forever until the lock is available, thus it is important that
|
* forever until the lock is available, thus it is important that
|
||||||
|
@ -43,12 +41,14 @@ public class SpinLock
|
||||||
|
|
||||||
public Lock lock()
|
public Lock lock()
|
||||||
{
|
{
|
||||||
Thread thread = Thread.currentThread();
|
Thread current = Thread.currentThread();
|
||||||
while(true)
|
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");
|
throw new IllegalStateException("SpinLock is not reentrant");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,7 @@ public class SpinLock
|
||||||
|
|
||||||
public boolean isLocked()
|
public boolean isLocked()
|
||||||
{
|
{
|
||||||
return _lock.get()!=null;
|
return _lock.get() != null;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLockedThread()
|
|
||||||
{
|
|
||||||
return _lock.get()==Thread.currentThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Lock implements AutoCloseable
|
public class Lock implements AutoCloseable
|
||||||
|
|
|
@ -18,17 +18,16 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.util.thread;
|
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.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class SpinLockTest
|
public class SpinLockTest
|
||||||
{
|
{
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocked()
|
public void testLocked()
|
||||||
{
|
{
|
||||||
|
@ -70,7 +69,6 @@ public class SpinLockTest
|
||||||
assertFalse(lock.isLocked());
|
assertFalse(lock.isLocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContend() throws Exception
|
public void testContend() throws Exception
|
||||||
{
|
{
|
||||||
|
@ -121,7 +119,7 @@ public class SpinLockTest
|
||||||
};
|
};
|
||||||
thread1.start();
|
thread1.start();
|
||||||
// thread1 will be spinning here
|
// thread1 will be spinning here
|
||||||
assertFalse(held1.await(100,TimeUnit.MILLISECONDS));
|
assertFalse(held1.await(100, TimeUnit.MILLISECONDS));
|
||||||
|
|
||||||
// Let thread0 complete
|
// Let thread0 complete
|
||||||
hold0.countDown();
|
hold0.countDown();
|
||||||
|
@ -135,8 +133,5 @@ public class SpinLockTest
|
||||||
thread1.join();
|
thread1.join();
|
||||||
|
|
||||||
assertFalse(lock.isLocked());
|
assertFalse(lock.isLocked());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue