Java 实现一个自己的显式锁Lock(有超时功能)

Lock接口

package concurency.chapter9;

import java.util.Collection;

public interface Lock {
    static class TimeOutException extends Exception {
        TimeOutException(String message) {
            super(message);
        }
    }

    void lock() throws InterruptedException;

    void lock(long mills) throws InterruptedException,TimeOutException;

    void unlock();

    Collection<Thread> getBlockedThread();

    int getBlockedSize();
}

Lock实现类

package concurency.chapter9;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

public class BooleanLock implements Lock{
    public BooleanLock(boolean initValue) {
        this.initValue = initValue;
    }

    // false means is free
    // true means having been used
    private boolean initValue;

    private Thread currentThread;

    private Collection<Thread> blockedThreads = new ArrayList<>();

    @Override
    public synchronized void lock() throws InterruptedException {
        while(initValue) {
            blockedThreads.add(Thread.currentThread());
            this.wait();
        }

        blockedThreads.remove(Thread.currentThread());
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
        // less than 0, Ignore it..
        if(mills <= 0)
            lock();
        long hasRemaining = mills;
        long endTime = System.currentTimeMillis() + mills;
        while(initValue) {
            if(hasRemaining <= 0)
                throw new TimeOutException("time out, and the Thread[" + Thread.currentThread().getName()+"] do not get the lock");
            blockedThreads.add(Thread.currentThread());
            this.wait(mills);
            hasRemaining = endTime - System.currentTimeMillis();
        }
        blockedThreads.remove(Thread.currentThread());
        this.initValue = true;
        this.currentThread = Thread.currentThread();
    }

    @Override
    public synchronized void unlock() {
        if(currentThread != null && Thread.currentThread() == currentThread) {
            this.initValue = false;
            Optional.of(Thread.currentThread().getName() + " release the lock...").ifPresent(System.out::println);
            this.notifyAll();
        }
    }

    @Override
    public Collection<Thread> getBlockedThread() {
        return Collections.unmodifiableCollection(blockedThreads);
    }

    @Override
    public int getBlockedSize() {
        return blockedThreads.size();
    }
}

测试

package concurency.chapter9;

import java.util.Optional;
import java.util.stream.Stream;

public class LockTest {
    public static void main(String[] args) throws InterruptedException {

        final BooleanLock booleanLock = new BooleanLock(false);
        Stream.of("T1", "T2", "T3", "T4")
                .forEach(name ->
                        new Thread(() -> {
                            try {
                                booleanLock.lock(1000L);
                                Optional.of(Thread.currentThread().getName() + " have the lock Monitor")
                                        .ifPresent(System.out::println);
                                work();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            } catch (Lock.TimeOutException e) {
                                System.out.println(e.getMessage());
//                                Optional.of(Thread.currentThread().getName() + " time out")
//                                        .ifPresent(System.out::println);
                            } finally {
                                booleanLock.unlock();
                            }
                        }, name).start()
                );
    }

    private static void work() throws InterruptedException {
        Optional.of(Thread.currentThread().getName() + " is Working...")
                .ifPresent(System.out::println);
        Thread.sleep(10_000);
    }
}

测试结果

T1 have the lock Monitor
T1 is Working...
time out, and the Thread[T2] do not get the lock
time out, and the Thread[T3] do not get the lock
time out, and the Thread[T4] do not get the lock
T1 release the lock...

原文地址:https://www.cnblogs.com/Draymonder/p/10381412.html

时间: 2024-10-07 01:30:14

Java 实现一个自己的显式锁Lock(有超时功能)的相关文章

并发编程—4显式锁 Lock

目录 4.显式锁 Lock 4.1 概念 内置锁 vs 显示锁 可重入锁 vs 不可重入锁 公平锁 vs 非公平锁 读锁 vs 写锁 4.2 ReentrantLock源码解读 4.显式锁 Lock 4.1 概念 内置锁 vs 显示锁 synchronize是java语言层面实现的锁,称为内置锁.使用方便代码简洁,而且在jdk新版本优化后,性能也得到了很大的提高.synchronize是一个可重入锁.而Lock是jdk提供开发者是用的一个显式锁.通过lock()和unlock()方法加锁和释放锁

Java并发编程系列-(4) 显式锁与AQS

4 显示锁和AQS 4.1 Lock接口 核心方法 Java在java.util.concurrent.locks包中提供了一系列的显示锁类,其中最基础的就是Lock接口,该接口提供了几个常见的锁相关的操作. public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit

java之AQS和显式锁

本次内容主要介绍AQS.AQS的设计及使用.ReentrantLock.ReentrantReadWriteLock以及手写一个可重入独占锁 1.什么是AQS? AQS,队列同步器AbstractQueuedSynchronizer的简写,JDK1.5引入的,是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作.AQS的作者Doug Lea大师期望它能够成为实现大部分同步需求的基础. 2.AQS的设计及其作用 Abst

JDK并发包温故知新系列(五)—— 显式锁与显式条件

显式锁-Lock与ReadWriteLockJDK针对Lock的主要实现是ReentrantLock,ReadWriteLock实现是ReentrantReadWriteLock.本文主要介绍ReentrantLock. ReentrantReadWriteLock两把锁共享一个等待队列,两把锁的状态都由一个原子变量表示,特有的获取锁和释放锁逻辑. ReentrantReadWriteLock的基本原理:读锁的获取,只要求写锁没有被线程持有就可以获取,检查等待队列,逐个唤醒等待读锁线程,遇到等待

显式锁(四)Lock的等待通知机制Condition

?? 任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( ).wait(long timeout).notify().notifyAll()方法:这些方法与关键字synchronized结合使用,可以实现 隐式锁的等待/通知机制.而显示锁Lock也实现了等待/通知机制:Condition接口也提供了类似Object的监视器方法,与Lock配合使用可以实现 显式锁的等待/通知机制,但是两者在使用方式和功能特性有所差别.总得来说,Condition接口更加灵

第13章 显式锁

性能是一个不断变化的指标,如果在昨天的测试基准中发现X比Y更快,那么在今天就可能已经过时了. 在激烈竞争的情况下,在非公平锁的性能高于公平锁的性能的一个原因是:在恢复一个被挂起的线程与该线程真正开始运行之间存在着严重的延迟.假设线程A持有一个锁,并且线程B请求这个锁.由于这个锁已被线程A持有,因此B将被挂起.当A释放锁时,B将被唤醒,因此会再次尝试获取锁.与此同时,如果C也请求这个锁,那么C很可能会在B被完全唤醒之前获得.使用以及释放这个锁.这样的情况是一种“双赢”的局面:B获得锁的时刻并没有推

Java显式锁学习总结之二:使用AbstractQueuedSynchronizer构建同步组件

Jdk1.5中包含了并发大神Doug Lea写的并发工具包java.util.concurrent,这个工具包中包含了显示锁和其他的实用同步组件.Doug Lea在构建锁和组件的时候,大多是以队列同步器(AbstractQueuedSynchronizer)为基础的,因此AbstractQueuedSynchronizer可以看作是并发包的基础框架.因此掌握了AbstractQueuedSynchronizer的实现原理,也就掌握了大多数并发组件的实现原理. AbstractQueuedSync

Java显式锁学习总结之五:ReentrantReadWriteLock源码分析

概述 我们在介绍AbstractQueuedSynchronizer的时候介绍过,AQS支持独占式同步状态获取/释放.共享式同步状态获取/释放两种模式,对应的典型应用分别是ReentrantLock和Semaphore,AQS还可以混合两种模式使用,读写锁ReentrantReadWriteLock就是如此. 设想以下情景:我们在系统中有一个多线程访问的缓存,多个线程都可以对缓存进行读或写操作,但是读操作远远多于写操作,要求写操作要线程安全,且写操作执行完成要求对当前的所有读操作马上可见. 分析

Java显式锁学习总结之一:概论

我们都知道在java中,当多个线程需要并发访问共享资源时需要使用同步,我们经常使用的同步方式就是synchronized关键字,事实上,在jdk1.5之前,只有synchronized一种同步方式.而在jdk1.5中提供了一种新的同步方式--显示锁(Lock).显示锁是随java.util.concurrent包一起发布的,java.util.concurrent包是并发大神Doug Lea写的一个并发工具包,里面除了显示锁,还有许多其他的实用并发工具类. 什么是显示锁 什么是显示锁?用一段代码