多线程相关概念的梳理(个人理解)

零零散散已经接触了很多有关多线程的概念了,这篇博客主要做一个总结,梳理一下这些概念,以及从宏观的角度来看多线程相关的问题是怎么产生的,又是怎么解决的。

多线程的意义

最常听到的一句话就是“多线程能提高效率”,但是多线程为什么提高了效率呢,或者说多线程一定会提高效率吗?

这里得分情况讨论:

单核处理器下,多线程的意义主要是为了能同时处理多个任务,大部分情况下不能提高提高效率,因为上下文切换也是需要开销的,但有些时候也能起到提高效率的作用,譬如某个线程在进行IO操作了,那么这个时候切换线程很明显就提高了效率,只不过这个不作为主要目的。

而在多核处理器下,由于有多个核心负责运行指令,多线程很明显就一下将效率提上去了。

多线程产生的问题

多线程非常便利,所以很多时候不得不多线程,但这也会增加系统设计难度,因为会导致线程安全问题,即数据不一致

数据不一致本质上是由于CPU一般都是将线程要读写的变量先拷贝到缓存,导致线程对变量的操作都是在缓存上的,无法直接操作主内存,这就造成了数据不一致。这也是为什么不变类就不会有多线程问题,因为这个类的实例都是不会改变的,一旦你修改了这个变量,那么一定是返回一个新的被修改的变量,譬如String类就没有多线程问题。

多线程中的锁

为了解决多线程带来的问题,出现了的概念。锁在处理器级别是有指令支持的,譬如X86架构的芯片,有lock prefix的指令就能做到原子操作,这样的指令不仅无法被打断,而且会锁住总线,或者锁住缓存。

在此基础上,操作系统层面依靠这些指令,就自己实现了一些锁供用户使用,比如互斥锁,自旋锁。于是我们在使用对应编程语言提供的库的时候,就能方便的用这些现成的锁。但你也可以依靠库中的一些别的方法,比如java.util.concurrent.atomic包,自己去实现锁,以保证多线程安全。这也就是常说的无锁编程,无锁编程不是说没有锁,只是说没有用到操作系统提供的锁。这比用锁编程的好处是没有死锁问题,同时效率也会得到一定提升(没有了操作系统去维护秩序,比如互斥锁的上下文切换问题)。不过这也引来了新的问题,比如ABA问题。通常无锁编程的实现难度会变得更大。

参考链接

  1. C++ 中,std::atomic 是真正的「原子」吗?
  2. 锁底层的实现原理

猜你喜欢

转载自blog.csdn.net/weixin_55658418/article/details/129433678