1、 底层实现上来说
synchronized是JVM层面的锁,是Java关键字,通过monitor对象来完成(monitorenter 与monitor exit),对象只有在同步块或同步方法中才能调用wait/notify方法,ReentrantLock 是从 jdkl.5 以来(java.util.concurrent.locks.Lock)提供的 API 层面的锁。
synchronized的实现涉及到锁的升级,具体为无锁、偏向锁、自旋锁、向OS申请重量级锁, ReentrantLock实现则是通过利用CAS (CompareAndSwap)自旋机制保证线程操作的原子性和 volatile保证数据可见性以实现锁的功能。
2、 是否可手动释放:
synchronized不需要用户去手动释放锁,synchronized代码执行完后系统会自动让线程释放 对锁的占用;ReentrantLock则需要用户去手动释放锁,如果没有手动释放锁,就可能导致 死锁现象。一般通过lock()和unlock()方法配合try/finally语句块来完成,使用释放更加 灵活。
3、 是否可中断
synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成; ReentrantLock 则可以中断,可通过 trylock(long timeout,TimeUnit unit)设置超时方法或 者将locklnterruptibly()放到代码块中,调用interrupt方法进行中断。
4、 是否公平锁
synchronized为非公平锁ReentrantLock则即可以选公平锁也可以选非公平锁,通过构造方 法new ReentrantLock时传入boolean值进行选择,为空默认false非公平锁,true为公平 锁。
5、 锁是否可绑定条件Condition
synchronized 不能绑定;ReentrantLock 通过绑定 Condition 结合 await()/singal()方法实现线程的精确唤醒,而不是像synchronized通过Object类的wait()/notify()/notifyAll() 方法要么随机唤醒一个线程要么唤醒全部线程。
6、 锁的对象
synchronzied锁的是对象,锁是保存在对象头里面的,根据对象头数据来标识是否有线程获 得锁/争抢锁;ReentrantLock锁的是线程,根据进入的线程和int类型的state标识锁的获得/争抢。
主要区别如下:
1、 ReentrantLock使用起来比较灵活,但是必须有释放锁的配合动作;
2、 ReentrantLock必须手动获取与释放锁,而synchronized不需要手动释放和开启锁;
3、 ReentrantLock只适用于代码块锁,而synchronized可以修饰类、方法、变量等。
4、 二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加 锁,synchronized操作的应该是对象头中mark word
5、 Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
1、 普通同步方法,锁是当前实例对象
2、 静态同步方法,锁是当前类的class对象
3、 同步方法块,锁是括号里面的对象

Was this helpful?

0 / 0

发表回复 0

Your email address will not be published.