21. Java中的锁机制有哪些?它们的区别和适用场景是什么?
-
锁机制:
- synchronized关键字:基于对象的内置锁(监视器锁),只能用于同步方法或同步代码块,简单易用,但灵活性较差。
- ReentrantLock:显示锁,提供了比synchronized更多的功能,如可中断锁、超时获取锁、公平性选择等,适合复杂的同步需求。
-
区别和适用场景:
synchronized
适合简单的同步场景,使用方便且性能较好,但不具备灵活性。ReentrantLock
适合复杂的同步需求,能够提供更多的功能和定制选项,但使用上相对复杂。
22. Java中的并发工具类有哪些?它们各自解决了什么问题?
-
并发工具类:
- CountDownLatch:允许一个或多个线程等待其他线程完成操作。
- Semaphore:控制同时访问特定资源的线程数。
- CyclicBarrier:一组线程相互等待,直到所有线程都达到某个公共屏障点。
- Phaser:提供更灵活的线程同步机制,可以动态注册参与者。
-
解决的问题:
- 这些工具类解决了多线程协作中的各种同步和控制问题,如线程间的等待、资源的并发访问控制、分阶段任务的协作等。
23. Java中的volatile关键字有什么作用?何时使用它?
- volatile关键字:
- 保证变量在多线程间的可见性,即一个线程修改了volatile修饰的变量,其他线程能立即看到修改后的值。
- 不保证原子性,不能替代synchronized。
- 适合状态标志、简单的计数器等场景。
24. Java中的线程间通信方式有哪些?它们各自的特点是什么?
-
线程间通信方式:
- wait()和notify()/notifyAll():基于对象监视器实现的等待/通知机制,用于线程之间的协作。
- 管道(PipedInputStream/PipedOutputStream):提供了基于流的线程间通信方式。
- 并发集合类(如BlockingQueue):提供了线程安全的队列操作,用于生产者-消费者模式等场景。
-
特点:
wait()
和notify()/notifyAll()
适用于多个线程之间精细的协作。- 管道适合于需要基于流的数据交换场景。
- 并发集合类提供了更高效的线程安全操作。
25. Java中的CAS(Compare and Swap)是什么?它在并发编程中的作用是什么?
-
CAS:
- CAS是一种乐观锁技术,通过比较当前值与期望值是否相等,来决定是否更新当前值。
- 在并发编程中,用于实现无锁数据结构和并发算法,提高了并发性能。
-
作用:
- 实现了原子操作,避免了使用传统锁带来的性能损失和复杂性。
- 适用于并发量较大、锁竞争激烈的场景。
26. Java中的原子类是什么?如何使用原子类实现线程安全操作?
-
原子类:
- Java中的原子类是一组提供了原子操作的类,如
AtomicInteger
、AtomicLong
等。 - 使用了CAS操作来保证操作的原子性,避免了使用锁的性能开销。
- Java中的原子类是一组提供了原子操作的类,如
-
使用方法:
- 实例化原子类对象。
- 调用原子类提供的方法进行原子操作,如
incrementAndGet()
、compareAndSet()
等。
27. Java中的Fork/Join框架是什么?如何使用它实现并行计算?
-
Fork/Join框架:
- 是Java7引入的并行计算框架,基于工作窃取算法实现。
- 主要包含
ForkJoinPool
、ForkJoinTask
和RecursiveTask
等类。
-
使用方法:
- 继承
RecursiveTask
或RecursiveAction
编写任务。 - 将任务提交给
ForkJoinPool
执行。 - 框架会自动根据工作量和CPU核心数进行任务划分和调度,实现任务的并行计算。
- 继承
28. Java中的ThreadLocal是什么?它解决了什么问题?
-
ThreadLocal:
- ThreadLocal提供了线程局部变量的功能,每个线程都有自己的变量副本,互不干扰。
- 解决了多线程环境下共享变量可能引发的线程安全问题。
-
问题:
- 在多线程环境中,共享变量的修改可能导致竞态条件、数据不一致等问题。
- ThreadLocal通过为每个线程提供独立的变量副本,避免了共享变量的修改和同步操作,提高了并发性能。
29. Java中的AQS(AbstractQueuedSynchronizer)是什么?它在并发框架中的角色是什么?
-
AQS:
- AQS是Java并发框架中的一个基础框架,提供了用于构建锁和同步器的基础设施。
- 主要通过内置的FIFO队列(等待队列)实现线程的阻塞和唤醒机制。
-
角色:
- 在并发框架中,AQS提供了可重入锁、读写锁等同步器的基础实现。
- 自定义同步组件时,可以继承AQS并重写指定方法,实现特定的同步语义和控制逻辑。
30. Java中的并发编程有哪些常见的问题和挑战?如何解决它们?
-
常见问题和挑战:
- 线程安全性问题(如竞态条件、死锁、活锁等)。
- 性能问题(如锁竞争、上下文切换等)。
- 可伸缩性问题(如线程池大小选择、任务调度等)。
-
解决方法:
- 使用同步机制(如synchronized、Lock)保证线程安全。
- 使用并发工具类和线程池优化性能和资源利用率。
- 设计合理的并发模型和算法,避免竞态条件和死锁。