这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战
Synchronized和Lock
Synchronized修饰方法的话,其他同步阻塞的方法,就必须等待该方法的synchronized区域结束释放锁,才能执行。
-
特性
- synchronized是Java的内置关键字
- Lock是一个接口类,在JDK1.5之后出现
- lock();
- lockInterruptibly() throws InterruptedException;
- boolean tryLock();
- boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
- void unLock();
- Condition newCondition();
-
公平性
- synchronized是非公平的,也就是不遵循线程访问资源的顺序,这也就有可能导致某些线程永远获取不到资源
- Lock是公平的,遵循线程访问资源的顺序
-
乐悲观
- Synchronized是基于CPU的悲观锁,在获取了资源后,其他的同步方法就只能阻塞等待,直至synchronized方法结束,释放资源
- Lock是乐观的,基于假想没有冲突(CAS),如果获取资源失败,则重试获取,直至成功
-
释放锁
- Synchronized只有执行结束后才会释放锁,如果中间遇到某些原因阻塞(如:sleep),则其他线程也只能等待
- Lock必须用try/catch方法修饰,并在finally区域内调用unlock方法释放锁,否则不会释放,造成死锁
-
读写锁
-
Synchronized无法实现,读锁共享,写锁排他的类似功能,锁住后读写都没有区别,只能阻塞
-
Lock可以实现ReadLock和WriteLock
- 读锁可以共享,但是读锁过程中,会阻塞写锁
- 写锁期间,读写都会阻塞
-
-
业务选型
- 在资源竞争少的时候,Synchronized和Lock的性能相差不大
- 但是在资源竞争大的时候,Lock会更好,因为Synchronized会浪费更多的资源在CPU频繁的切换上下文
总结
- Lock锁是API层面的,Synchronized是CPU层面的
- 相对来说,Lock锁更灵活;这是优点,同时也是缺点,需要程序员更加关注unLock的释放使用,避免死锁。
- 尽管Synchronized比较重量级,但是JVM从JDK1.6开始也在不断地优化,支持锁升级,但是reentrantlock更强大,有tryLock不会傻傻的一直等,非常人性化,还能避免死锁。