面试官:有了解过Synchronized吗 说说看("面试官提问:你对Synchronized了解多少?详细谈谈")
原创
面试官提问:你对Synchronized了解多少?详细谈谈
在Java多线程编程中,synchronized
关键字是一个非常重要的同步机制,用于控制多个线程对共享资源的访问。下面我将详细介绍synchronized
的相关知识。
1. Synchronized的基本概念
synchronized
关键字可以用于方法或代码块,确保同一时刻只有一个线程可以执行某个方法或代码块。它提供了内置的锁机制,当一个线程访问一个对象的synchronized
方法或代码块时,其他线程必须等待该线程执行完毕才能继续执行。
2. Synchronized的使用做法
synchronized
关键字有两种使用做法:修饰方法和修饰代码块。
2.1 修饰方法
当synchronized
修饰一个方法时,它的锁对象是当前实例对象实例(对于实例方法)或类的Class对象(对于静态方法)。
public synchronized void synchronizedMethod() {
// 方法体
}
2.2 修饰代码块
当synchronized
修饰代码块时,需要指定一个锁对象。进入同步代码块之前,线程必须获得指定锁对象的锁。
public void synchronizedBlock() {
synchronized(this) {
// 代码块
}
}
3. Synchronized的锁机制
synchronized
通过Monitor(监视器)来实现锁机制。Monitor是一种数据结构,每个Java对象都可以作为Monitor。Monitor中有两种状态:锁定状态和非锁定状态。
- 当线程尝试进入一个同步块或同步方法时,如果Monitor处于锁定状态,线程将被挂起,并进入等待状态。
- 当Monitor的锁定状态变为非锁定状态时,等待在该Monitor上的线程会被唤醒,并尝试获取锁。
4. Synchronized的优化
Java虚拟机(JVM)对synchronized
进行了优化,核心包括以下几种:
- 偏向锁:当锁被一个线程访问后,如果没有其他线程竞争,这个锁会偏向于这个线程。
- 轻量级锁:当没有竞争或竞争不激烈时,使用轻量级锁来避免使用重量级的操作系统互斥量。
- 自旋锁:当线程尝试获取一个已经被其他线程持有的锁时,它会循环检查锁是否已经释放,而不是立即挂起。
5. Synchronized的注意事项
在使用synchronized
时,需要注意以下几点:
- 避免在同步块或同步方法中调用其他同步方法,以降低锁的粒度。
- 尽量降低同步块或同步方法的长度,以降低线程等待时间。
- 避免在同步块或同步方法中执行I/O操作或调用外部资源,以降低锁的持有时间。
- 避免使用
synchronized
来控制非线程保险的操作,如修改数组大小。
6. Synchronized与ReentrantLock的比较
synchronized
和ReentrantLock
都是Java中的锁机制,但它们有以下不同之处:
synchronized
是Java关键字,编译器会在编译时自动插入锁操作指令;而ReentrantLock
是Java类,需要手动加锁和解锁。ReentrantLock
提供了更灵活的锁操作,如尝试非阻塞地获取锁、尝试在给定时间内获取锁、中断等待锁的线程等。ReentrantLock
拥护公平锁和非公平锁,而synchronized
只能拥护非公平锁。ReentrantLock
需要手动处理异常,而synchronized
会自动释放锁。
7. 总结
synchronized
是Java多线程编程中常用的同步机制,通过内置的锁机制来保证线程保险。懂得synchronized
的原理和优化策略,以及怎样正确使用它,对于编写高效、稳定的多线程程序至关重要。