面试题:线程安全3问

Posted 格子衫111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题:线程安全3问相关的知识,希望对你有一定的参考价值。

一、一共有哪 3 类线程安全问题?

什么是线程安全:

当多个线程访问一个对象时,不需要考虑不能同时写入或者读写不能并行的问题,也不需要做额外的同步操作,那么就说这个对象是线程安全的。

1)运行结果错误:如两个线程同时访问共享变量i,执行1000次 i++操作,未加同步操作;

2)发布和初始化引发的线程安全问题:如子线程还未给一个对象初始化,主线程就去访问,得到的是null;

3)活跃性问题

死锁:如两个线程各拿到对方的锁不愿意释放;

活锁:如消息队列中报错的消息被重复放到队列头进行执行;

饥饿:如某个线程优先级被设置很低(1最低),导致一直获取不到CPU资源无法运行。


二、哪些场景需要额外注意线程安全问题?

1)访问共享变量或缓存时:如两个线程同时对全局变量进行i++操作;

2)依赖时序的操作:如单例对象懒汉式创建时的双重校验;

3)不同数据之间存在绑定关系:如IP和端口号,需要绑定在一起成为一个原子操作;

4)访问了线程不安全的对象:如ArrayList。


三、为什么多线程会带来性能问题?

什么是性能问题:

比如服务器的响应慢、吞吐量低、内存占用过多就属于性能问题。

线程调度开销:

上下文切换:

操作系统会按照一定的调度算法,给每个线程分配时间片,上下文切换会挂起当前线程,寻找下一处即将恢复的代码。假如执行的任务比较简单,可能导致线程调度的开销比实际执行的内容还要大。

缓存失效:

当前一个任务缓存好内容后,切换到另外一个线程,随后再切换回来,刚刚缓存的内容不见啦,又得重新计算,这就是线程调度所带来的缓存失效。

ps:为了避免频繁进行上下文切换,线程调度器会给被调度的线程设置最小执行时间。

线程协作开销:

多线程协作时,往往为了线程安全,可能会禁止编译器或者CPU指令重排序(如violate),为了数据的内存可见性,可能会在线程工作内存和主存中来回反复flash,带来性能开销。

以上是关于面试题:线程安全3问的主要内容,如果未能解决你的问题,请参考以下文章

被一个熟悉的面试题问懵了:StringBuilder 为什么线程不安全?

多线程 面试题—线程安全

Java线程安全和非线程安全

一个读写锁面试题

一个读写锁面试题

Java集合面试题总结