并发(多线程)------>ReentrantLock(上)初步解读与实例

前言:ReentrantLock   从英文上来看  re+entrant+Lock  说明他是一个可重入锁(文中解释)。

 

源码中的注释如下:

* A reentrant mutual exclusion {@link Lock} with the same basic
* behavior and semantics as the implicit monitor lock accessed using
* {@code synchronized} methods and statements, but with extended
* capabilities.

归纳1:它有synchronized锁的基本功能,但是它还有更多的功能

* <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
* successfully locking, but not yet unlocking it. A thread invoking
* {@code lock} will return, successfully acquiring the lock, when
* the lock is not owned by another thread. The method will return
* immediately if the current thread already owns the lock. This can
* be checked using methods {@link #isHeldByCurrentThread}, and {@link
* #getHoldCount}.

归纳2:在没有释放(unlock)ReentrantLock之前,它会一致持有。

* <p>The constructor for this class accepts an optional
* <em>fairness</em> parameter.  When set {@code true}, under
* contention, locks favor granting access to the longest-waiting
* thread.  Otherwise this lock does not guarantee any particular
* access order.  Programs using fair locks accessed by many threads
* may display lower overall throughput (i.e., are slower; often much
* slower) than those using the default setting, but have smaller
* variances in times to obtain locks and guarantee lack of
* starvation. Note however, that fairness of locks does not guarantee
* fairness of thread scheduling. Thus, one of many threads using a
* fair lock may obtain it multiple times in succession while other
* active threads are not progressing and not currently holding the
* lock.
* Also note that the untimed {@link #tryLock()} method does not
* honor the fairness setting. It will succeed if the lock
* is available even if other threads are waiting.

归纳3:构造器接受一个公平的参数来设置ReentrantLock是公平锁还是非公平的(文末解释公平非公平)

归纳4:公平锁比默认的非公平锁吞吐率低(为什么?请思考,在最后会讲明),但在获取锁的时间上有较小的差异,并保证不出现饥饿现象。锁的公平性并不能保证线程调度的公平性,在许多使用公平锁的线程中,其中一个线程可能会连续多次获得公平锁,而其他活动线程则没有进展。

 

综上:对于ReentrantLock可以获得如下简要结论

1 有synchronized的基本功能   

2 它不像synchronized一样是隐式锁,是显式的(上面的归纳2中可以看出)

3 增加可公平和非公平的参数 默认非公平的(性能比公平锁高)

 

额外问题

1 什么是重入锁:重入又名递归,一个线程在持有锁的情况下在进入该所不会发生死锁,可重入的

 

2 公平锁和非公平锁:公平就是按照访问锁的顺序要获得锁,非公平就是请求锁的顺序和获取锁的顺序不同。

 

3 为什么公平锁比默认的非公平锁吞吐率低(性能差)?(下面是综合查看其他博文算是较好的例子吧,感觉没有从操作系统底层讲明白这个问题,都是泛泛而谈了,不过也算不错了,回头我再从操作系统底层来作答一下)

答案1:恢复一个挂起的线程与该线程真正执行之间存在严重的延迟,因为CPU的寄存器缓存和高速缓存都可能失效,需要重新载入数据。这时,如果将锁交给执行时间很短的任务,那么可以充分利用在被唤起线程真正开始执行之前的数据准备时间,从而提高了性能。从此处可以看出,当线程持有锁的时间比较长(执行任务需要的时间长)或者请求锁的平均时间间隔比较长,则应该使用公平锁。

答案2:公平锁要维护一个队列,后来的线程要加锁,即使锁空闲,也要先检查有没有其他线程在 wait,如果有自己要挂起,加到队列后面,然后唤醒队列最前面的线程。这种情况下相比较非公平锁多了一次挂起和唤醒

线程切换的开销,其实就是非公平锁效率高于公平锁的原因,因为非公平锁减少了线程挂起的几率,后来的线程有一定几率逃离被挂起的开销。

 

4 为什么公平锁有时候会出现多次占用一个锁的例子?(最上面归纳4)

源码中对这个问题的解释:公平锁是说明锁公平,它与操作系统对线程的调度无关。比如完成这一系列任务,操作系统觉得A线程要执行4次,B,C再依次执行,这时候就会出现公平锁也会有一个线程多次占用锁的情况

 

了解了上述的归纳和总结我们对ReentrantLock有一个简要的认知

ReentrantLock  显式  默认非公平(效率高) 可重入锁

实际操作一个案例吧:

线程A-Z线程输出自己的名字:

public class MyTest {
    public static void main(String[] args) {
        ReentrantLock a = new ReentrantLock();//默认非公平的
        char ThreadName = 'A';
        for(int i=0;i<26;i++){
            new Thread(new MyThread(a), String.valueOf(ThreadName)).start();
             ThreadName =(char) ++ThreadName;
        }
    }

}
class MyThread implements Runnable{

    ReentrantLock reentrantLock;
    MyThread(ReentrantLock reentrantLock){
        this.reentrantLock = reentrantLock;
    }
    @Override
    public void run() {
        reentrantLock.lock();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
        reentrantLock.unlock();
    }
}

结果:

A
B
C
D
E
F
H
G
I
J
L
K
N
M
O
P
R
S
Q
U
T
V
W
X
Y
Z
延时是为了观察    锁住了 其他线程不能进来

输出结果来看:不管我们ReentrantLock设置成公平的还是非公平的,它都会出来乱序的情况  也就是不完全按照A-Z的顺序输出的      这也反映了我们线程的先后和操作系统调度的先后不一致的情况

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值