使用 while 循环等待其他锁释放,而不是让出 CPU 时间片。(使用原子操作 CAS - atomic 类型数据)
可以减少线程切换,但可能长时间占用等待。(不可重入自旋锁、可重入自旋锁)
不可重入自旋锁
// 自旋锁,不可重入。因为如果同意线程,即run方法中,多次调用lock,则会死锁
class SpinLock {
AtomicReference<Thread> sign = new AtomicReference<Thread>();
public void lock() {
Thread thread = Thread.currentThread();
while (!sign.compareAndSet(null, thread)) {
}
}
public void unlock() {
Thread thread = Thread.currentThread();
sign.compareAndSet(thread, null);
}
}
可重入自旋锁
// 自旋锁,可重入。通过计数器记录锁次数
class SpinLock {
AtomicReference<Thread> sign = new AtomicReference<Thread>();
private int count;
public void lock() {
Thread thread = Thread.currentThread();
if (thread == sign.get()) {
count++;
return;
}
while (!sign.compareAndSet(null, thread)) {
}
}
public void unlock() {
Thread thread = Thread.currentThread();
if (count > 0) {
count--;
} else {
sign.compareAndSet(thread, null);
}
}
}
使用
import java.util.concurrent.atomic.AtomicReference;
public class Test {
public static void main(String[] args) throws InterruptedException {
SpinLock lock = new SpinLock();
for (int i = 0; i < 100; i++) {
SpinLockTest t = new SpinLockTest(lock);
Thread tt = new Thread(t);
tt.start();
}
Thread.currentThread().sleep(3000);
System.out.println(SpinLockTest.getNum());
}
}
class SpinLockTest implements Runnable {
private static int num;
private SpinLock lock;
public SpinLockTest(SpinLock lock) {
this.lock = lock;
}
@Override
public void run() {
lock.lock();
lock.lock();
System.out.println(num);
num++;
lock.unlock();
lock.unlock();
}
public static int getNum() {
return num;
}
}