1、Java中volatile与synchronized有什么区别,分别作用于哪些场景 ?
2、synchronized和juc中的锁比较分别适用于哪些场景 ?
3、既要保证线程安全又要尽可能提升性能,怎么取得平衡 ?
4、分布式场景中,如何实现一个全局锁 ?
5、对于一个8核的的高性能CPU来说在多线程场景下是不是线程池设置的越大越好?如何确定线程池的大小,设置不当会带来什么问题 ?
思考下,或者写一写,再看答案,你一定可以,加油!!!
1、Java中volatile与synchronized有什么区别,分别作用于哪些场景
- volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.
- volatile仅能使用在变量级别,synchronized则可以使用在变量,方法中.
- volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.
- volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.
- volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.
2、synchronized和juc中的锁比较分别适用于哪些场景
- ReentrantLock在内存上的语义与synchronize相同, 但是它提供了额外的功能, 可以作为一种高级工具. 当需要一些可定时, 可轮询, 可中断的锁获取操作, 或者希望使用公平锁, 或者使用非块结构的编码时才应该考虑 ReentrantLock .
- 在业务并发简单清晰的情况下推荐synchronized, 在业务逻辑并发复杂, 或对使用锁的扩展性要求较高时, 推荐使用 ReentrantLock 这类锁.
3、既要保证线程安全又要尽可能提升性能,怎么取得平衡
- 分析业务场景,尽可能的实现无锁编程;
- 对于并发场景,尽可能的缩小锁的范围;(这里可以看看jdk7在 ConcurrentHashMap中的 Segment 的思想,这是一种分段锁思想,在开发过程中也是会遇到的。 )
4、分布式场景中,如何实现一个全局锁
- 使用数据库实现;
- 使用缓存实现;(可以是zookeeper,也可以是redis)
能够回答出来,用一个全局唯一的资源来满足资源竞争的顺序执行和原子性就行。
5、对于一个8核的的高性能CPU来说在多线程场景下是不是线程池设置的越大越好?如何确定线程池的大小,设置不当会带来什么问题
- 并非越大越好,线程池大小的设置要根据CPU处理的任务特征来区别对待。
- 如果线程执行的是CPU密集型任务服务器的物理内核数就应该被视为是有限的资源,这样创建的线程数就不应该超过系统的内核数。
- 如果线程执行的是IO密集型任务就要根据IO的占比和速度进行性能测试来确认线程池的大小。
- 线程池大小设置的过小或者过大都会导致系统产生问题无法利用系统资源,如果线程池的线程数量过少这使得用户需要花费很长时间来等待请求的响应。但是,如果允许创建过多的线程,会产生线程不断切换,系统的资源又会被耗尽,这会对系统造成更大的破坏,甚至宕机。