并发同步学习笔记

Synchronized、ReentrantLock的区别?

要回答这两者的区别,我们先要搞懂如下概念
要搞明白的概念——可重入锁,定时锁等候tryLock(),中断锁等候lockInterruptibly()
——ReentrantLock的lock机制有2种,忽略中断锁和响应中断锁
——ReentrantLock这个类还提供了2种竞争锁的机制:公平锁和非公平锁。
——Condition

=========================

可重入锁:如果当前线程已经持有此锁,再次请求,则计数增加1

=========================

响应中断锁
在JDK5之前使用Synchronized作为获取锁的关键字,但是在获取锁的过程中无法中断,即使调用Thread.interrupt也不会中断。
为了能够使线程快速的响应中断,可以使用lock.lockInterruptibly()方法。
lock.lockInterruptibly()函数的具体执行过程
获取锁,除非当前线程被中断。
如果锁没有被其他线程持有,则获取锁并立即返回,将锁保持计数设置为1。
如果当前线程已经持有此锁,则保持计数增加1,方法立即返回。
如果锁被另一个线程持有,那么为了线程调度目的,当前线程将被禁用,并处于休眠状态,直到发生以下两种情况之一:
锁是由当前线程获取的;
或其他一些线程中断当前线程。
如果锁被当前线程获取,那么锁保持计数被设置为1。
如果当前线程:在进入此方法时设置其中断状态;或在获取锁时被中断,然后抛出InterruptedException,并清除当前线程的中断状态。
在这个实现中,由于该方法是一个显式的中断点,所以优先考虑对中断的响应,而不是对锁的正常获取或重入获取。

=========================

tryLock方法的解释?
如果锁在给定的等待时间内没有被另一个线程持有,并且当前线程没有被中断,则获取锁。
如果锁没有被其他线程持有,则获取锁,并立即返回值true,将锁保持计数设置为1。如果将此锁设置为使用公平排序策略,那么如果其他线程正在等待锁,则不会获得可用的锁。这与tryLock()方法相反。如果你想要一个有时间限制的尝试,那就把有时间限制的和没有时间限制的表单合并在一起:
如果(lock.tryLock()| |
锁。tryLock(超时、单位)){

} }
如果当前线程已经持有此锁,则保持计数增加1,方法返回true。
如果锁被另一个线程持有,那么为了线程调度目的,当前线程将被禁用,并处于休眠状态,直到发生以下三种情况之一:
锁是由当前线程获取的;
或其他一些线程中断当前线程;
或指定的等待时间运行
如果获取锁,则返回值true,并将锁保持计数设置为1。
如果当前线程:
在进入此方法时设置其中断状态;或在获取锁时被中断,
然后抛出InterruptedException,并清除当前线程的中断状态。
如果指定的等待时间流逝,则返回值false。如果时间小于或等于零,则该方法根本不会等待。
在这个实现中,由于该方法是一个显式的中断点,所以优先考虑响应中断,而不是常规的或重入的获取锁,以及报告等待时间的流逝。
指定:tryLock(…)in Lock
参数:
超时等待锁的时间
单元超时参数的时间单位
返回:
如果锁是空闲的,并且被当前线程获取,或者锁已经被当前线程持有;如果在获取锁之前等待时间过长,则为false
抛出:
InterruptedException -如果当前线程被中断
NullPointerException—如果时间单元为空

Condition
ReentrantLock可以与Condition的配合使用,Condition为ReentrantLock锁的等待和释放提供控制逻辑。

例如,使用ReentrantLock加锁之后,可以通过它自身的Condition.await()方法释放该锁,线程在此等待Condition.signal()方法,然后继续执行下去。await方法需要放在while循环中,
因此,在不同线程之间实现并发控制,还需要一个volatile的变量,boolean是原子性的变量。

ReentrantLock lock  = new ReentrantLock();
Condtion processReady = lock.newCondtion();

while(!isProcessReady) {  //isProcessReady 是另外一个线程的控制变量
      processReady.await();//释放了lock,在此等待signal
     }

==================

什么是自旋锁?
很多线程在等待锁的时候,在很短的一段时间就获得了锁,所以它们在线程等待的时候,并不需要把线程挂起,而是让他无目的的循环,一般设置10次。这样就避免了线程切换的开销,极大的提升了性能。

=========================
Synchronized、ReentrantLock的区别
1.synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中;
2.在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
3.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情(tryLock()、tryLock(timeout, unit) 或者lockInterruptibly()方法)
4.ReentrantLock这个类还提供了2种竞争锁的机制:公平锁和非公平锁。这2种机制的意思从字面上也能了解个大概:即对于多线程来说,公平锁会依赖线程进来的顺序,后进来的线程后获得锁。而非公平锁的意思就是后进来的锁也可以和前边等待锁的线程同时竞争锁资源。对于效率来讲,当然是非公平锁效率更高,因为公平锁还要判断是不是线程队列的第一个才会让线程获得锁。

=============

什么情况下用ReentrantLock?
1.某个线程在等待一个锁的控制权的这段时间需要中断
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程
3.具有公平锁功能,每个到来的线程都将排队等候

=============
什么是锁投票?

参考资料:
http://baijiahao.baidu.com/s?id=1571946569081893&wfr=spider&for=pc
https://www.cnblogs.com/2390624885a/p/6675876.html
https://blog.csdn.net/fatherican/article/details/53674005
https://www.cnblogs.com/fanguangdexiaoyuer/p/5313653.html
https://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1

你可能感兴趣的:(Core,JAVA,并发同步)