混合型自旋锁 纯自旋锁在竞争激烈的情况下会频繁的自旋浪费CPU资源, 所以一般使用混合型自旋锁进行改进,在尝试了一定次数后进入休眠状态
public class HybridSpinLock {
// 自旋次数
private static final int TRY_TIMES = 20;
// 最多等待多长时间
private static final int MAX_WAIT_MILLIS_ECONDS = 1000;
// 锁标志
private AtomicReference<HybridSpinLock> obj = new AtomicReference<HybridSpinLock>();
// 当前等待的线程数量
private AtomicInteger waitCount = new AtomicInteger(0);
public void lock() {
int times = 0;
while (!obj.compareAndSet(null, this)) {
times++;
if (times % TRY_TIMES == 0) {
try {
synchronized (obj) {
System.out.println("线程等待");
waitCount.addAndGet(1);
obj.wait(MAX_WAIT_MILLIS_ECONDS);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 通过设置锁标志为null释放锁
* 如果有等待的线程,唤醒一个
*/
public void unlock() {
obj.set(null);
// 等待线程的数量
int waitCountNum = waitCount.get();
while (true) {
if (waitCountNum > 0
&& waitCount.compareAndSet(waitCountNum, waitCountNum - 1)) {
// 当有等待的线程时唤醒一个
synchronized (obj) {
System.out.println("唤醒一个线程");
obj.notify();
}
break;
}
waitCountNum = waitCount.get();
//如果没有等待的线程跳出循环
if (waitCountNum <= 0)
break;
}
}
public static void main(String[] args) {
class Task implements Runnable {
private HybridSpinLock spinLock = new HybridSpinLock();
private long count = 0;
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
spinLock.lock();
count += 1;
count += 1;
// 模拟耗时操作,如果没有耗时操作,
//线程可能不会超出自旋次数,不进入等待状态
//尝试注释掉sleep后运行
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
spinLock.unlock();
}
}
}
public long getValue() {
return count;
}
}
// 线程数量
final int THREAD_NUM = 10;
Task task = new Task();
List<Thread> threads = new ArrayList<Thread>();
try {
for (int i = 0; i < THREAD_NUM; i++) {
Thread t = new Thread(task);
t.start();
threads.add(t);
}
for (Thread t : threads) {
t.join();
}
System.out.println("结果:" + task.getValue());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}