面试必问的多线程-1.3:lock和synchronized底层上有什么区别呢?

news/2024/5/17 19:42:30 标签: 面试, lock, synchronized

1)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。

Lock是一个类,通过这个类可以实现同步访问;

2)Lock和synchronized有一点非常大的不同,

采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;

而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

 

区别:

1:用法不一样

synchronized既可以加在方法上,也可以加在特定代码块上,其中括号中表示需要锁的对象。

而Lock需要显示地指定起始位置和终止位置。

synchronzied是托管给jvm执行的,Lock锁定是通过代码实现的。

2:在性能上来说,

如果竞争资源不激烈,两者的性能是差不多的,

如果竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized

所以说,在具体使用时要根据适当情况选择。

3:锁的机制不一样,

synchronized获得锁和释放的方式都是在块结构中,而且是自动释放锁。

而Lock则需要开发人员手动去释放,并且必须在finally块中释放,否则会引起死锁问题的发生。

4:Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

5:异常处理不一样,

synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;

而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

6:Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

Lock可以提高多个线程进行读操作的效率。

上面只是一些简单的理解,

当然面试回答这些是完全不够的,

 

 

Lock是java 1.5中引入的线程同步工具,它主要用于多线程下共享资源的控制。本质上Lock仅仅是一个接口(位于源码包中的javautilconcurrentlocks中)

Lock有三个实现类,一个是ReentrantLock,另两个是ReentrantReadWriteLock类中的两个静态内部类ReadLock和WriteLock。

使用方法:多线程下访问(互斥)共享资源时, 访问前加锁,访问结束以后解锁,解锁的操作推荐放入finally块中。

 

synchronizedlock他们的性能比较:

在JDK1.5中,synchronized是性能低效的。因为这是一个重量级操作,它对性能最大的影响是阻塞的是实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性带来了很大的压力。相比之下使用Java提供的Lock对象,性能更高一些。多线程环境下,synchronized的吞吐量下降的非常严重,而ReentrankLock则能基本保持在同一个比较稳定的水平上。

到了JDK1.6,发生了变化,对synchronize加入了很多优化措施,有自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在JDK1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地,所以还是提倡在synchronized能实现需求的情况下,优先考虑使用synchronized来进行同步。

因此基本上我们都使用synchronized

 

基本语法上,ReentrantLock与synchronized很相似,它们都具备一样的线程重入特性,只是代码写法上有点区别而已,一个表现为API层面的互斥锁(Lock),一个表现为原生语法层面的互斥锁(synchronized)。ReentrantLock相对synchronized而言还是增加了一些高级功能,主要有以下三项:

1、等待可中断:当持有锁的线程长期不释放锁时,正在等待的线程可以选择放弃等待,改为处理其他事情,它对处理执行时间非常上的同步块很有帮助。而在等待由synchronized产生的互斥锁时,会一直阻塞,是不能被中断的。

2、可实现公平锁:多个线程在等待同一个锁时,必须按照申请锁的时间顺序排队等待,而非公平锁则不保证这点,在锁释放时,任何一个等待锁的线程都有机会获得锁。synchronized中的锁时非公平锁,ReentrantLock默认情况下也是非公平锁,但可以通过构造方法ReentrantLock(ture)来要求使用公平锁。

3、锁可以绑定多个条件:ReentrantLock对象可以同时绑定多个Condition对象(名曰:条件变量或条件队列),而在synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含条件,但如果要和多于一个的条件关联的时候,就不得不额外地添加一个锁,而ReentrantLock则无需这么做,只需要多次调用newCondition()方法即可。而且我们还可以通过绑定Condition对象来判断当前线程通知的是哪些线程(即与Condition对象绑定在一起的其他线程)。
 

 

关于公平锁和非公平锁,我们下一章会将,这里在简单提一下:

公平锁和非公平锁

公平锁以请求锁的顺序来获取锁,非公平锁则是无法保证按照请求的顺序执行。synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。

读写锁

  读写锁将对一个资源(比如文件)的访问分成了2个锁,一个读锁和一个写锁。

  正因为有了读写锁,才使得多个线程之间的读操作不会发生冲突。

  ReadWriteLock就是读写锁,它是一个接口,ReentrantReadWriteLock实现了这个接口。

  可以通过readLock()获取读锁,通过writeLock()获取写锁。

 

Lock:Lock实现和synchronized不一样,后者是一种悲观锁。而Lock呢底层其实是CAS乐观锁的体现,它无所谓。

如果面试问起,你就说底层主要靠volatile和CAS操作实现的。

 

 

总结

  1.synchronized

  优点:实现简单,语义清晰,便于JVM堆栈跟踪,加锁解锁过程由JVM自动控制,提供了多种优化方案,使用更广泛

  缺点:悲观的排他锁,不能进行高级功能

  2.lock

  优点:可定时的、可轮询的与可中断的锁获取操作,提供了读写锁、公平锁和非公平锁  

  缺点:需手动释放锁unlock,不适合JVM进行堆栈跟踪

  3.相同点 

  都是可重入锁

 

 

 


http://www.niftyadmin.cn/n/1307916.html

相关文章

面试必问的多线程-1.4:各种锁介绍

认识的锁? 偏向锁 轻量级锁 重量级锁 重入锁 自旋锁 共享锁 独占锁\排它锁 读写锁 公平锁 非公平锁 死锁 活锁 1:偏向锁 是Java6引入的一项多线程优化,它会偏向于第一个访问锁的线程, 如果在运行过程中&#xff0c…

面试必问的Java-1.0:动态代理-静态代理

Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题。 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息&am…

分布式事务理解

事务是一组连续的操作,这一组操作要么都成功执行,要么都不能执行; 那么什么是数据库事务呢? 数据库事务一般具有以下几个特征: 原子性,构成事务的所有操作,要么都执行完成,要么全…

面试必问的数据库-3.1:索引-底层实现原理

索引可以加快查询的效率。 如果数据库没有加索引,sql中where是怎么执行查找到目标的? 举例: 如果想要查询表格第二列是怎么查找的? 如想查询where col222的记录,在没有加索引的情况下是按顺序从第一条记录开始查找&…

面试必问的数据库-3.2:索引-相关

1:数据库索引和选择性的关系 在讨论数据库索引的时候,经常会提到“选择性”(selectivity)这个概念。“选择性”是描述列值数据分布情况的一个重要属性。“选择性”和“基数”(cardinality)是两个密不可分的概念。“基数”就是一列中唯一值的数量&#x…

面试必问的数据库-4.1:sql-优化

1:关于批量插入数据(100万)数据优化 思路: 1:变多次提交为一次 2:使用批量操作 整理了两种方法: 方法一: 1. public static void insert() { 2. // 开时时间 3. …

面试必问的HashMap-1.1:HashMap几个关键点分析

HashMap都不算什么特别的,这里整理下我的理解。 分析HashMap就不得不说下数据结构, 首先Java中有几种数据结构:数组、链表、树 数组的话:查询效率高 链表新增效率高。 牛逼的是,我们的HashMap的数据接口就比较吊了…

面试必问的HashMap-2.1:CurrentHashMap

ConcurrentHashMap与HashMap等的区别 1.HashMap HashMap是线程不安全的,在多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。 2.HashTable HashTable和HashMap的实现…