synchronized和ReentrantLock

学习了Java锁相关的内容,简单的总结下几个问题,如有错漏,恳请指正


 

1.线程安全的基本特性

原子性:即一个操作是不可中断的,要么全部完成,要么全部不完成

有序性:禁止指令重排序,保证操作是有序的

可见性:一个线程的修改对另一个线程是立即可见的

volatile保证了有序性和可见性,不保证原子性

synchronized保证原子性,有序性和可见性

2.synchronized和ReentrantLock有什么区别?

synchronized和ReentrantLock都是java提供的用于同步的手段

synchronized可以用来修饰方法,也可以用来修饰代码块,修饰方法时本质上就是锁住方法中的所有代码块,synchronized的加锁和解锁都是隐式的

ReentrantLock需要显示加锁和解锁,相比较synchronized,可以提供可中断锁,公平锁,还可以利用Condition和signal,await方法创建多种条件

在低并发的情况下,synchronized的性能其实并不比ReentrantLock差,而在高并发情况下,ReentrantLock性能会优于synchronized

3.synchronized锁住的是什么?

一般情况下,synchronized锁方法和锁代码块,实际上锁住的都是当前对象,也就是该对象调用该代码块或方法时,才会被锁住。

具体而言,如果你创建了多个线程,每个线程中都创建一个新的对象,调用该对象的synchronized的方法,并不会感觉synchronized起作用了。

如果想要真正的锁住一段代码,要么synchronized(Demo.class)这样锁住类的对象,或者定义static synchronized方法,这样的话锁住的其实是该类的类对象,也就是该类创建的所有实例都会被锁住。

4.读写锁是怎么回事

不管是synchronized还是ReentrantLock,都具有独占性,但在实际的情况中,很多时候并不会出现大量竞争的写操作,而并发读实际上并不会出现线程安全问题。

读写锁就是Java针对这一问题进行的改性,它基于的原理是多个读操作是不需要互斥的,将读锁和写锁分离。

5.synchronized底层是怎么实现的,自旋锁,偏向锁,轻量级锁,重量级锁是怎么回事

synchronized底层是由monitorenter和monitorexit实现的,Monitor对象时同步实现的基本单元。

Java1.6以前,Monitor的实现完全是依靠操作系统内部的互斥所,而从1.6开始,进行了改进,也就是偏向锁,轻量级锁和重量级锁。

没有锁竞争时,会默认使用偏向锁,偏向当前线程,此时实际上并没有涉及到互斥锁。

当有第二个线程来进行锁时,会判断之前获取锁的线程是否还在运行中,如果已经释放锁,则偏向新的线程,否则会依赖CAS操作Mark Word来试图获取锁,如果成功,偏向锁会升级为轻量级锁,否则升级为重量级锁。

轻量级锁时乐观的,而重量级锁时悲观的,轻量级锁认为竞争的程度很轻,可以一个线程持有锁,另一个线程自旋,当第三个线程来试图获取锁,或者自旋超过一定时间,就会升级为重量级锁。

posted @ 2019-07-23 14:47  珞珈山的小狐狸  阅读(131)  评论(0)    收藏  举报