栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA面试考点——Reentrantlock

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA面试考点——Reentrantlock

目录

1. 作用

2. Lock

2.2 condition对象

3. ReentrantLock

3.1 Sync 对象

3.1.1  可重入以及可重入锁的概念

3.1.2 公平锁、非公平锁

4、java中断机制


1. 作用

ReentrantLock基于AQS,在并发编程中它可以实现公平锁和非公平锁来对共享资源进行同步。

同时,和synchronized一样,ReentrantLock支持可重入,除此之外,ReentrantLock在调度上更灵活,支持更多丰富的功能。

2. Lock

ReentrantLock 实现了Lock接口。

Lock的意义在于提供了区别于synchronized的另一个具有更多广泛操作的同步方式,他能支持更多灵活的结构,并且可以关联多个Condition对象。

package java.util.concurrent.locks;

import java.util.concurrent.TimeUnit;

public interface Lock {
    // 用于获取锁
    void lock();

    // 假设当前线程在等待锁,如果被中断,则会抛出中断异常
    void lockInterruptibly() throws InterruptedException;

    boolean tryLock();

    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    void unlock();

    // 新建一个绑定在当前lock上的condition对象
    Condition newCondition();
}

2.2 condition对象

表示一种等待状态。

比如获取锁的线程需要满足某些条件才能继续执行,那么他可以通过awit方法,注册在condition对象上进行等待,然后通过condition对象中的signal将其唤醒

一个lock上可以关联多个condition,多个线程可以被绑定在不同的condition上,这样就可以分组唤醒。

condition还实现了限时、中断相关功能,丰富了线程调度策略。

3. ReentrantLock
public class ReentrantLock implements Lock, java.io.Serializable {

    private static final long serialVersionUID = 7373984872572414699L;

    
    // 被final修饰,说明一旦被初始化就不可以被修改其引用的地址了
    private final Sync sync;

    
    abstract static class Sync extends AbstractQueuedSynchronizer {...}

    
    static final class NonfairSync extends Sync {...}

    
    static final class FairSync extends Sync {...}
       
}

3.1 Sync 对象
 
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        
        @ReservedStackAccess
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState(); // 获取aqs中的锁状态
            if (c == 0) {       // 锁空闲
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // 判断是否独占锁的线程是不是自己;如果不是,返回false,获取锁失败
            // 如果是自己获取了锁,那么实现可重入机制,并累计重入的次数
            // 因为释放时也需要释放相同的次数
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        // 返回值的true和false,代表是否被完全释放,而不是成功释放
        @ReservedStackAccess
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

3.1.1  可重入以及可重入锁的概念

可重入——单个线程执行时,  重新进入同一个子程序,  仍然是线程安全的. 。

可重入锁——即一个线程无需释放,而可以重复的获取锁n次;在释放时,也需要释放n次

3.1.2 公平锁、非公平锁

公平锁——按照请求锁的顺序分配;拥有稳定获得锁的机会;但是性能可能比非公平锁低

非公平锁——不按照请求锁的顺序分配;不一定拥有获得锁的机会;但是性能可能比公平锁高(因为线程的唤醒需要一定的时间,这段时间完全可以被抢占去利用)

    
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;
        
        @ReservedStackAccess
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            //如果锁不是空闲的,那么需要判断下当前锁是不是自己占据
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }
    }

4、java中断机制

 

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425399.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号