双重校验锁模式【其他模式】

@Slf4j
public class DoubleCheckedLock {

    /**
     * 双重校验锁模式可以避免多线程竞争时,无谓的资源消耗
     */
    @Test
    public void all() throws InterruptedException {
        final LimitedList<String> list = new LimitedList<>(1);
        final CountDownLatch latch = new CountDownLatch(1);
        final ExecutorService threadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 3; i++) {
            threadPool.submit(() -> {
                try {
                    latch.await();
                } catch (final InterruptedException e) {
                    log.error("failed", e);
                }
                list.add(Thread.currentThread().getName());
            });
        }
        latch.countDown();
        TimeUnit.SECONDS.sleep(3);
    }
}

@Data
@Slf4j
class LimitedList<E> {
    private final int maxSize;
    private final List<E> container;
    private final Lock lock;

    public LimitedList(int maxSize) {
        super();
        this.maxSize = maxSize;
        this.container = Lists.newArrayListWithCapacity(maxSize);
        this.lock = new ReentrantLock();
    }

    public boolean add(E e) {
        // 第一重校验
        if (container.size() < maxSize) {
            try {
                final String name = Thread.currentThread().getName();
                log.info("{} block1", name);
                lock.lock();
                log.info("{} block2", name);
                // 锁定后的第二重校验
                if (container.size() < maxSize) {
                    log.info("{} block3", name);
                    container.add(e);
                    return true;
                }
            } finally {
                lock.unlock();
            }
        }
        return false;
    }
}

猜你喜欢

转载自www.cnblogs.com/zhuxudong/p/10171026.html