130-如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能)

  1. 上一节中的问题:违规非法操作,导致运行混乱。巨大的BUG
  2. 让锁具备超时功能

上一节中的问题:违规非法操作,导致运行混乱。巨大的BUG

public static void main(String[] args) throws InterruptedException {
    final BooleanLock booleanLock = new BooleanLock();

    new Thread(() -> {
        try {
            booleanLock.lock();
            Optional.of(Thread.currentThread().getName() + " have the lock Monitor.").ifPresent(System.out::println);
            work();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            booleanLock.unlock();
        }
      }, "T1");

    // 问题:违规非法操作,导致运行混乱
    Thread.sleep(100);
    booleanLock.unlock();
}

锁booleanLock由线程T1中加锁lock(),就只能由T1解锁unlock()

解决:

private Thread currentThread;

@Override
public synchronized void lock() throws InterruptedException {
    ...
    this.currentThread = Thread.currentThread();
}

@Override
public synchronized void unlock() {
    // 释放锁
    if (Thread.currentThread() == currentThread) {
        ...
    }
}

synchronized机制导致的一个问题:synchronized不能被打断,导致其他线程抢不到锁。

public static void main(String[] args) throws InterruptedException {
    new Thread(SynchronizedProblem::run, "T1").start();
    Thread.sleep(1000);
    Thread t2 = new Thread(SynchronizedProblem::run, "T2");
    t2.start();

    Thread.sleep(2000);
    t2.interrupt();
    System.out.println(t2.isInterrupted());// true,但是并没有中断t2
}

private synchronized static void run() {
    System.out.println(Thread.currentThread().getName());
    while (true) { }
}

t2.isInterrupted()返回值为true,但是并没有中断t2,此时就需要让锁具备超时功能,即void lock(long mills),mills时间拿不到锁就会超时,同时抛出TimeOutException异常。

让锁具备超时功能

调用的方法一直阻塞,但是还有其他工作需要执行,此时放弃调用方法需要使用void lock(long mills)。等待锁指定时间,一旦时间超过就抛出TimeOutException

@Override
public synchronized void lock(long mills) throws InterruptedException, TimeOutException {
    if (mills <= 0) {
        lock();
    }

    long hasRemaining = mills;
    long endTime = System.currentTimeMillis() + mills;
    while (initValue) {
        if (hasRemaining <= 0) {
            throw new TimeOutException("Time Out");
        }
        blockedThreadCollection.add(Thread.currentThread());
        this.wait(mills);
        hasRemaining = endTime - System.currentTimeMillis();
    }
    this.initValue = true;
    this.currentThread = Thread.currentThread();
}

void wait()需要synchronized,需要添加一个Monitor锁

Java5之后JUC并发包提供了相同的功能。由大神Doug Lea开发,使Java性能更加接近于C/C++。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com

文章标题:130-如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能)

文章字数:429

本文作者:神秘的小岛岛

发布时间:2019-12-01, 22:29:09

最后更新:2019-12-07, 18:35:56

原始链接:https://www.tuyrk.cn/wang-thread/130-custom-lock-timedout/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏