美文网首页
Synchronized和ReentrantLock

Synchronized和ReentrantLock

作者: ohjam | 来源:发表于2019-02-12 17:20 被阅读4次

    Synchronized

    Synchronized也称内置锁,Java提供同步代码块这种内置的锁机制来支持原子性,同步代码块包括两个部分:一个作为锁的对象引用,一个作为由这个锁保护的代码块。注意synchronized并不是“为这一块代码”加锁,而是给Class对象加锁。

            synchronized (lock) {}
    

    每一个Java对象都能用作实现同步的锁,线程在进入同步代码块之前会自动获得锁,在退出同步代码块时自动释放锁。锁是互斥的,最多只有一个线程能持有这个锁,当A线程持有一个锁,B线程尝试获取这个锁时,B线程只能等待或者阻塞,直到A线程释放这个锁。
    内置锁是可重入的,一个线程获取一个由自己持有的锁,这样的请求是成功的。

    ReentrantLock

    ReentrantLock实现了Lock接口,Lock提供了一种无条件、可轮询、定时、可中断的锁获取操作,加锁和解锁都是显式的。ReentrantLock提供了跟跟内置锁相同的互斥性和内存可见性,提供了相同的可重入的特性。
    使用ReentrantLock必须在finally中释放锁,否则如果在代码中抛异常,那这个锁就永远都不能释放。

            // 示例
            ReentrantLock lock = new ReentrantLock();
            lock.lock();
            try {
              // ... method body
            } finally {
              lock.unlock();
            }
    

    Synchronized和ReentrantLock的区别

    在大多数情况下,内置锁都能很好的完成工作,但是它存在一些局限性,比如,无法中断一个正在等待获取锁的线程。但ReentrantLock也不能完全代替Synchronized,ReentrantLock需要更多的try-catch-finally代码。
    在你需要如下特性时,你可以选择使用ReentrantLock来解决你的问题:

    • 轮询锁和定时锁
    public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
    }
    public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
    

    马上返回结果和带时间限制的tryLock方法。

    • 可中断的锁获取操作
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
    

    调用后一直阻塞到获得锁,但是接受中断信号。

    • 非块结构的加锁

    可重入的实现原理

    重入的一种实现方法是,为每个锁关联一个获取计数值和一个所有者线程,当计数值为0时,这个锁就被认为是没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1。如果同一个线程再次获取这个锁时,计数值将递增,当线程退出同步代码块时,计数值会递减。当计数值为0时,这个锁将释放。

    相关文章

      网友评论

          本文标题:Synchronized和ReentrantLock

          本文链接:https://www.haomeiwen.com/subject/llqiaftx.html