实现
自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
自旋锁是互斥锁的一种实现,Java 实现如下方所示。
public class SpinLock {
private AtomicReference<Thread> owner = new AtomicReference<Thread>();
public void lock() {
Thread currentThread = Thread.currentThread();
// 如果锁未被占用,则设置当前线程为锁的拥有者
while (!owner.compareAndSet(null, currentThread)) {
}
}
public void unlock() {
Thread currentThread = Thread.currentThread();
// 只有锁的拥有者才能释放锁
owner.compareAndSet(currentThread, null);
}
}
测试
测试代码如下:
public class SpinLockTest {
public static class Accumulator implements Runnable {
SpinLock lock = new SpinLock();
int i;
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
lock.lock(); // 加锁
i++;
lock.unlock(); // 解锁
}
}
}
public static void main(String[] args) throws InterruptedException {
Accumulator accumulator = new Accumulator();
Thread t1 = new Thread(accumulator);
Thread t2 = new Thread(accumulator);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(accumulator.i); // 预期值 20000
}
}
输出如下:
20000
Process finished with exit code 0
优缺点
优点:
- 自旋锁实现简单,同时避免了操作系统进程调度和线程上下文切换的开销。
缺点:
- 第一个是锁饥饿问题。在锁竞争激烈的情况下,可能存在一个线程一直被其他线程“插队”而一直获取不到锁的情况。
- 第二是性能问题。在实际的多处理上运行的自旋锁在锁竞争激烈时性能较差。