简单锁类
package com.fangshirui;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
/**
* 简单锁的实现
*
* @author fangshirui
*/
public class SimpleLock {
/**
* 要借助AtomicReference提供的CAS方法支持原子性,而且AtomicReference中的value
* 已经加了volatile实现不同线程的可见性,最终实现线程安全。
*/
private final AtomicReference<Thread> owner = new AtomicReference<>();
/**
* 阻塞队列
*/
private final LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>();
/**
* 争夺锁方法
*/
public void lock() {
while (!tryLock()) {
waiters.add(Thread.currentThread());
// 将当前线程阻塞
LockSupport.park();
}
waiters.remove(Thread.currentThread());
}
public boolean tryLock() {
// if owner.value == null , then make owner.value = currentThread
// 内存语义: 获取锁方法 == CAS更新volatile变量
// 禁止重排序、将写缓冲区所有数据刷新到主内存中 ==> 内存屏障
// 在刷新volatile变量前,会将本地所有共享变量置为无效,重新从主内存中获得。
return owner.compareAndSet(null, Thread.currentThread());
}
/**
* 释放锁
*/
public void unlock() {
// 内存语义: 释放锁方法 == CAS更新volatile变量
// 禁止重排序、将写缓冲区所有数据刷新到主内存中 ==> 内存屏障
// 在刷新volatile变量前会将本地内存所有共享变量全部刷新到主内存中。
if (owner.compareAndSet(Thread.currentThread(), null)) {
if (!waiters.isEmpty()) {
// 将线程池中所有线程都激活,他们会争抢锁
waiters.forEach(LockSupport::unpark);
}
}
}
}
客户端使用
package com.fangshirui;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author fangshirui
*/
public class LockTest {
private int i = 0;
SimpleLock myLock = new SimpleLock();
private void add(){
myLock.lock();
try{
i++;
}finally {
myLock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
LockTest lockTest = new LockTest();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 4; i++) {
executorService.submit(() ->{
for (int j = 0; j < 10000; j++) {
lockTest.add();
}
});
}
Thread.sleep(2000);
System.out.println(lockTest.i);
executorService.shutdown();
}
}
输出:
40000
不使用简单锁,而使用内置的原子类AtomicInteger
package com.fangshirui;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author fangshirui
*/
public class LockTest {
private final AtomicInteger i = new AtomicInteger(0);
private void add(){
i.addAndGet(1);
}
public static void main(String[] args) throws InterruptedException {
LockTest lockTest = new LockTest();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 4; i++) {
executorService.submit(() ->{
for (int j = 0; j < 10000; j++) {
lockTest.add();
}
});
}
Thread.sleep(2000);
System.out.println(lockTest.i.get());
executorService.shutdown();
}
}
输出:
40000