synchronized和ReentrantLock

synchronized 特性:

1.是可重入锁;

2.锁方法时,锁的是this;

3.锁静态时,锁的是xxx.calss;

4.锁定方法和非锁定方法可以同步执行;

5.异常锁,程序执行中,如果出现异常,默认情况下,锁会被释放;

6.可以保证原子性和可见性。

7.可重入锁,父子类的继承可实现

synchronized 锁升级过程:(只能升级不能降级)

锁对象头部的两位(00:无锁,01:偏向锁,10:自旋锁,11:重量级锁)

1.无锁;

2.偏向锁:

当只有一个线程时,先尝试不对这个线程加锁,只记录这个线程的ID,默认这个对象是这个线程独有的;

3.自旋锁

如果有其他线程来了,就升级为自旋锁。此时占cpu,不经过内核

如果线程锁中已有线程id记录,则后来的线程就会先进行自旋,默认自旋10次,如果依旧拿不到锁,就会升级为重量级锁。

应用:加锁代码执行时间短,并且线程少的情况下,用自旋锁。

4.重量级锁

线程自旋10次后,若还没拿到锁,自旋锁升级为重量级锁-OS锁.

升级为重量级锁后,会进入waitting区,不再占用cpu

应用:加锁代码执行时间长,线程数多时 选用

synchronized使用时需注意:

1.不能用String;

2.不能用Integer;

3.不能用Long;

锁优化

1.锁细化:减少同步代码块

2.锁粗化:线程争用特别频繁时选用

ReentrantLock常用方法:

lock()/unlock() 获得锁,释放锁

tryLock()判断是否可得到锁,返回true/false 

lockInteruptibly()可以被打断,对interrupt()做出响应

new ReentrantLock(true)创建公平锁,检查队列中是否有等待的线程,有则进入等待队列

可以通过condition绑定多个条件

synchronized和 ReentrantLock 有什么不同

1.synchronized 是自动加锁解锁的,而 ReentrantLock是需要手动加锁解锁的;

2.sychronized底层实现是锁升级,而ReentrantLock底层实现是cas

3.synchronized 是JVM层面的锁,是Java关键字,而ReentrantLock 是API层面的锁

4.是否可中断:synchronized是不能中断的,除非加锁代码出现异常,或者执行完成才能释放锁,而ReentrantLock 是可以中断的,可通过trylock(long timeout,TimeUnit unit)设置超时方法,或者lockInterruptibly()放到代码块中,调用interrupt方法进行中断。

5.是否公平锁:synchronized是非公平锁,而ReentrantLock 是可以通过构造方法传boolean 值来选择 公平还是非公平,不传则默认非公平。

6.锁是否可绑定多个条件:synchronized不能绑定。ReentrantLock可以通过绑定Condition结合await()/Singal方法实现线程的精确唤醒,而不像synchronized通过Object类的wait()/notify()/notifyAll() 要么随机唤醒一个线程要么全部唤醒

7.锁的对象。synchronized锁的是对象,锁是保存在对象头里面的,根据对象头数据来标识是否有线程来获得锁、争抢锁。ReentrantLock 锁的是线程,根据进入的线程和int 类型的state标识锁的获得和争抢。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值