博主将会针对 Java 面试题写一组文章,包括 J2ee ,SQL,主流Web框架, 中间件 等面试过程中面试官经常问的问题,欢迎大家关注。一起学习,一起成长。文章底部有面试题。
synchronized
对象锁 :使用 synchronized 修饰 非静态 的方法以及 synchronized(this) 同步代码块使用的锁是对象锁。
类锁 :使用 synchronized 修饰 静态 的方法以及 synchronized(class) 同步代码块使用的锁是类锁。
私有锁 :在类内部声明一个私有属性如private Object lock ,在需要加锁的同步块使用 synchronized(lock)
它们的特性:
- 对象锁具有可重入性。
- 当一个 线程 获得了某个对象的对象锁,则该线程仍然可以调用其他任何需要该对象锁的 synchronized 方法或 synchronized(this) 同步代码块。
- 当一个线程访问某个对象的一个 synchronized(this) 同步代码块时,其他线程对该对象中所有其它 synchronized(this) 同步代码块的访问将被阻塞,因为访问的是同一个对象锁。
- 每个类只有一个类锁,但是类可以 实例化 成对象,因此每一个对象对应一个对象锁。
- 类锁和对象锁不会产生竞争。
- 私有锁和对象锁也不会产生竞争。
- 使用私有锁可以减小锁的细粒度,减少由锁产生的开销。
ReentrantLock
ReentrantLock 是一个独占/排他锁。相对于 synchronized,它更加灵活。但是需要自己写出加锁和解锁的过程。它的灵活性在于它拥有很多特性。
它的特性:
- 公平性 :支持公平锁和非公平锁。默认使用了非公平锁。
- 可重入
- 可中断 :相对于 synchronized,它是可中断的锁,能够对中断作出响应。
- 超时机制 :超时后不能获得锁,因此不会造成 死锁 。
ReentrantReadWriteLock
它拥有读锁(ReadLock)和写锁(WriteLock),读锁是一个共享锁,写锁是一个排他锁。
它的特性:
- 公平性 :支持公平锁和非公平锁。默认使用了非公平锁。
- 可重入 :读线程在获取读锁之后能够再次获取读锁。写线程在获取写锁之后能够再次获取写锁,同时也可以获取读锁(锁降级)。
- 锁降级 :先获取写锁,再获取读锁,然后再释放写锁的过程。锁降级是为了保证数据的可见性。