同步: synchronized和ReentrantLock

5 篇文章 0 订阅
开头给自己得渣渣发音备注下: synchronized读法: ['sɪŋkrənaɪzd] 

       ReentrantLock和synchronized都是加锁式同步,当一个线程获取了对象锁后,其它要进入同步块的线程就必须阻塞在同步块外等待。线程的阻塞和唤醒需要操作系统在用户态和内核态之间切换,所以,ReentrantLock和synchronized都是代价比较高的。

  •  关于用户态和内核态得解释,摘自百度百科如下:

           内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序。

           用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取。

  •  为什么要有用户态和内核态?

            由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 -- 用户态和内核态。

  • 实现方式

     synchronized的锁机制是JVM实现的,是原生语法层面的;synchronized是Java的关键字.

     ReentrantLock是API层面的锁,需在代码里面调用api逻辑来实现.

     所以synchronized在使用上更简单方便一些,但是从灵活层面来说,ReentranLock更加灵活,可以根据api来灵活使用,可控性更强,可以实现更细粒度.

    ps: 在使用ReentrantLock时,一定要注意lock和unlock的匹配和顺序,否则就可能造成死锁。常见的方案是把unlock放在异常处理的finally语句块中。

  • 性能 

    synchronized性能在jdk1.5之前较差,jdk1.6之后逐步优化,锁机制的升级,引入轻量级锁,偏向锁.官方更推荐使用synchronized,因为二者现在性能差不多,且synchronized使用起来更简单方便,避免使用ReentrantLock过程中,可能使用不当造成死锁.

  • 公平锁 

           公平锁指的是,是否根据排队的顺序获取到锁,如A线程目前获取到锁,后面排队还有BCDEF五个线程,A执行完,把锁给B,B执行完给C持续下去;如果是非公平锁,在A执行完,把锁一扔,BCDEF五个线程抢锁,谁抢到轮到谁. 

    synchronized是非公平锁,ReentrantLock默认也是非公平锁,但是ReentrantLock可以实现公平锁.通过new ReentrantLock(true)可以用来构造一个公平锁.

  • 是否可重入锁 

   可重入锁指的是一个线程可以对某个资源重复加锁,最常见的就是递归,如线程A调用了方法B,B是加锁的,A线程获取了B的锁,如果B中递归调用了B自己,需要再次获取B的锁,持续下次,直到退出.synchronized和ReentrantLock都是可重入锁.

  •  ReentrantLock更灵活

    1.ReentrantLock更灵活主要提现在实现方式是API,可以根据API逻辑来自由实现;

    2.ReentrantLock可以通过lockInterruptibly()方法来打断等待的线程,转去执行其他的线程.

    3.另外有时我们不希望在一个锁结束后,唤醒全部的线程,而是唤醒部分线程,这种方式在synchronized下是无法实现的。但是,ReentrantLock通过提供一个Contition类,可以同时绑定多个对象,来实现线程的分组唤醒。

   4.提供公平锁机制的实现.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值