Java中锁的介绍

本文将介绍Java并发包中与锁相关的组件,以及这些API和组件的使用方式和实现细节。

1.Lock接口

  锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能够防止多个线程同时访问共享资源(但是优先锁可以允许多个线程并发的访问共享资源,比如读写锁)。在Lock接口出现之前,Java程序靠synchronized关键字实现锁的功能。而Java SE 5以后,并发包中新增了Lock接口,用来实现锁的功能,只是在使用的时候需要显示的获取和释放锁。虽然他缺少了隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字所不具备的1同步特性。

  使用synchronized关键字将会隐式地获取锁,但是他将锁的获取和释放固化了,也就是先获取在释放。当然这种方式简化了同步的管理,可是扩展性没有显示的锁获取和释放来的好。

Lock接口提供的synchronized关键字所不具备的主要特性

特性描述
尝试非阻塞地获取锁当前线程尝试获取锁,如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁
能被中断地获取锁与synchronized不同,获取到锁的线程能够响应中断,当获取锁的线程被中断时,中断异常将会抛出,同时锁会被释放
超时获取锁在指定的截止时间之前获取锁,如果截止时间到了仍旧无法获取锁,则返回

2.队列同步器

  队列同步器AbstractQueuedSynchronizer(AQS),是用来构建锁或其他同步组件的基础框架,他使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。
  同步器是实现锁的关键,在锁的实现中聚合同步器,利用同步器实现锁的语义。可以这样理解二者之间的关系:锁是面向使用者的,他定义了使用者与锁交互的接口,隐藏了实现细节;同步器面向的是锁的实现者,他简化了锁的实现方式,屏蔽了同步状态管理、线程排队、等待与唤醒等底层操作。
  同步器提供的模板方式基本上分为3类:独占式获取释放同步状态、共享式获取释放同步状态、和查询同步队列中的等待线程情况。下面我们通过一个独占锁的示例了解一下同步器的工作原理。
  顾名思义独占锁就是在同一时刻只有一个线程获取到锁,而其他获取锁的线程只能处理同步队列中等待,只有获取锁的线程释放了锁,后继的线程才能获取锁。

public class Mutex implements Lock {

    /**
     * 静态内部类,自定义同步器
     */
    private static class Sync extends AbstractQueuedLongSynchronizer {

        /**
         * 是否处理占用状态
         *
         * @return boolean
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        /**
         * 当状态为0的时候获取锁
         *
         * @param arg arg
         * @return boolean
         */
        @Override
        protected boolean tryAcquire(long arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        /**
         * 释放锁,将状态设置为0
         *
         * @param arg arg
         * @return boolean
         */
        @Override
        protected boolean tryRelease(long arg) {
            if (getState() == 0) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // 返回一个ConditionObject,每一个condition包含一个condition队列
        Condition newCondition() {
            return new ConditionObject();
        }

    }

    private final Sync sync = new Sync();

    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }

    public boolean isLocked() {
        return sync.isHeldExclusively();
    }

    public boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值