1、在我们实际使⽤中,线程池的⼤⼩配置多少合适?
对于计算密集型,设置 线程数 = CPU数 + 1;
对于I/O密集型,线程数 = CPU数 * CPU利⽤率 * (任务等待时间 / (任务计算时间 + 1)) 。
2、死锁的四个必要条件:
- 互斥
- 请求和保持
- 不可剥夺
- 环路等待
3、终止线程的方法:shutdown
4、让核心线程实现一直存活的方法:take
volatile能保证可见性,不能保证原子性,保证有序性(指令重排)
5、Volatile和Synchronized区别?
volatile只能修饰实例变量和类变量,⽽synchronized可以修饰⽅法,以及代码块。
volatile保证数据的可⻅性(当有的线程修改了Volatile修饰的变量值并写回到主内存后,其他线程能⽴即看到最新的值)。但是不保证原⼦性(多线程进⾏写操作,不保证线程安全)。
⽽synchronized是⼀种排他(互斥)的机制。 volatile⽤于禁⽌指令重排序:可以解决单例双重检查对象初始化代码执⾏乱序问题。
volatile可以看做是轻量版的synchronized,volatile不保证原⼦性,但是如果是对⼀个共享变量进⾏多个线程的赋值,⽽没有其他的操作,那么就可以⽤volatile来代替synchronized,因为赋值本⾝是有原⼦性的,⽽volatile⼜保证了可⻅性,所以就可以保证线程安全了。
volatile可以通过加锁来保证原子性。
6、指令重排
是指编译器或CPU为了优化程序的执行性能而对指令进行重新排序的一种手段,但重排序会带来可见性问题,所以在多线程开发中必须要关注并规避重排序。
编译器和cpu处理器都遵守”as-if-serial语义“,保证单线程
7、as-if-serial
表示所有的程序指令都可以因为优化而被重排序,但是在优化的过程中必须要保证是在单线程环境下,重排序之后的运行结果和程序代码本身预期的执行结果一致,Java编译器、CPU指令重排序都需要保证在单线程环境下的as-if-serial语义是正确的。
不存在数据依赖的操作,可能会被编译器和cpu指令重排,Volatile通过设置内存屏障来防止指令重排,内存屏障是一个CPU的指令,它可以保证特定操作的执行顺序。从而避免多线程环境下程序乱序执行的现象。
8、内存屏障分为四种:
- StoreStore屏障
- StoreLoad屏障
- LoadLoad屏障
- LoadStore屏障