ReentrantLock你知道多少呢?

1、公平性锁和非公平性锁
非公平性:如果一个线程因为CPU时间全部被其他的线程抢走而无法获得CPU的执行时间,这种状态称之为饥饿,而该线程被称为“饥饿致死”,非公平锁就存在“饥饿”,因为线程得不到CPU的运行时间机会。
公平性:所有的线程均能公平性的获取到执行的机会
2、Java的线程饥饿原因:
1、高优先级的线程抢夺所有的低优先级的线程CPU时间
2、线程被永久阻塞在一个等待进入同步块的状态
3、线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的wait方法)
3、公平性锁的实现:
Lock类转换为公平锁FairLock,原理是:每一个Lock调用的线程都回去进入到队列,当解锁后,只有队列中的第一个线程被允许获取锁
4、ReentrantLock实现
ReentrantLock是Java中的课重入锁的一种实现,一次只能有一个线程持有锁,也就是独占锁的概念
包含三个内内部类:Sync、NonFairSync、FairSync,公平性锁和非公平性锁通过构造函数来指定
public class ReentrantLock implements Lock, java.io.Serializable {
//默认的非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}

  //fair决定是公平性锁和非公平性锁 true:公平锁 false:非公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }
    
    //加锁
    public void lock() {
        sync.lock();
    }
    
    //非公平性锁实现
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }
    
    //释放锁
    public void unlock() {
        sync.release(1);
    }
    
    public Condition newCondition() {
        return sync.newCondition();
    }
   
   //判断有线程在等待锁
   public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }
}

使用示例
公平锁和非公平锁的不同
A、B两个线程不断的获取共享的变量,为了保证变量的并发安全,分别使用公平锁和非公平锁实现加锁操作
实现类:

public class NonFairAndFairDemo implements Runnable {
    private static Integer num = 0;
    private ReentrantLock rtl;
    public NonFairAndFairDemo(ReentrantLock rtl) {
        this.rtl = rtl;
    }
    @Override
    public void run() {
        while (true) {
            //显性加锁
            rtl.lock();
            num++;
            System.out.println(Thread.currentThread().getName()+":"+num);
            //显性释放锁
            rtl.unlock();
        }
    }
}

注意:Lock锁的使用:
加锁和释放锁是显性调用
加锁和释放锁必须成对出现
多把锁的使用遵循先加锁后释放,后加锁先释放的原则

ReentrantLock源码分析

未完待续…

发布了68 篇原创文章 · 获赞 2 · 访问量 1665

猜你喜欢

转载自blog.csdn.net/weixin_45923633/article/details/105703142
今日推荐