Java并发面试题, Java 中的线程安全是什么意思?
Java并发面试题, Java 中的线程安全是什么意思?
QA
Step 1
Q:: Java 中的线程安全是什么意思?
A:: 线程安全是指在多线程环境中,多个线程访问和修改共享数据时,能够正确地进行同步,保证数据的完整性和一致性。具体来说,就是确保一个线程在执行某段代码时,其他线程不能访问该段代码,直到执行完毕。常见的实现线程安全的方法包括使用同步块、锁机制(如ReentrantLock)、原子变量(如AtomicInteger)和并发集合(如ConcurrentHashMap)。
Step 2
Q:: 如何实现 Java 中的线程安全?
A:: 实现 Java 中的线程安全有多种方法,主要包括:
1.
同步方法和同步块:使用 synchronized 关键字锁定方法或代码块,确保同一时间只有一个线程可以访问。
2.
显示锁:如 ReentrantLock 提供更灵活的锁定机制,可以响应中断、限时等待。
3. **原子变量**:使用 java.util.concurrent.
atomic 包中的原子变量类,如 AtomicInteger、AtomicLong,确保操作的原子性。
4. **并发集合类**:使用 java.util.
concurrent 包中的并发集合类,如 ConcurrentHashMap、CopyOnWriteArrayList,保证线程安全的集合操作。
5.
局部变量:局部变量是线程安全的,因为每个线程都有自己的栈空间。
Step 3
Q:: 什么是死锁?如何避免死锁?
A:: 死锁是指两个或多个线程相互等待对方释放锁,从而都进入无限等待状态。避免死锁的方法包括:
1.
避免嵌套锁:尽量减少嵌套锁的使用,避免多个锁相互依赖。
2.
按顺序加锁:保证所有线程按照相同的顺序获得锁,避免循环等待。
3. **使用尝试锁机制**:如 tryLock()
方法,在获取不到锁时进行处理而不是无限等待。
4.
定时锁机制:使用带超时参数的锁方法,避免长时间等待锁。
Step 4
Q:: 什么是 volatile 关键字?
A:: volatile 关键字用于标记一个变量是线程共享的,即它的值在多个线程之间是可见的。使用 volatile 修饰的变量,保证所有线程读取该变量时,获取的都是最新的值,而不是使用缓存。volatile 适用于某些简单的同步场景,但不能替代 synchronized,因为它无法保证复合操作的原子性。
Step 5
Q:: 什么是乐观锁和悲观锁?
A:: 乐观锁和悲观锁是两种处理并发的策略:
1.
悲观锁:假定会发生冲突,线程在访问共享资源前先获得锁,其他线程只能等待锁释放。这种策略常见于数据库中的行锁。
2.
乐观锁:假定不会发生冲突,线程在修改数据时检查是否有其他线程修改过,若有则重试操作。Java 中的 CAS(Compare And Swap)机制是乐观锁的实现方式。