多线程实现方式:
Synchronized和ReentrantLock区别:
相似点:都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒代价很高
功能区别:Synchronized,是Java关键字,是原生语法层面的互斥,需要jvm实现
ReentrantLock是JDK1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语法块来加锁和释放锁
便利性:Synchronized使用简洁,并且由编译器去保证锁得加锁和释放,而ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好在finally中声明释放锁;
CAS(乐观锁):每次不加锁而是假设有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止
ReentrantLock,是java.util.concurrent包下提供得一套互斥锁,三个高级功能
- 等待可中断,持有锁得线程长期不释放得时候,正在等待得线程选择放弃等待,这相当于Synchronized来说避免出现死锁得情况,通过lock.lockInterruptibly()来实现这个机制。
- 公平锁,多个线程等待同一个锁时,必须按照申请锁得时间顺序执行,Synchronized锁非公平锁,ReentrantLock默认得构造函数时创建得非公平锁,可以通过参数true设为公平锁,但公平锁表现得性能不是很好,默认非公平
- 锁绑定多个条件,一个ReentrantLock对象可以同时绑定多个对象,ReenTrantLock提供了一个Condition(条件类)用来实现分组唤醒需要唤醒得线程们,而不像synchronized要么随机唤醒一个线程,要么全部唤醒
ReentrantLock实现原理:Reentrant Lock的实现时一种自旋锁,通过循环调用CAS操作来实现加锁。它的性能比较好也是因为避免了使线程进入内核态的阻塞状态。