并发编程的挑战

157 阅读3分钟

为什么需要并发编程?

并发编程的目的是为了提高程序运行速度。

并发编程存在什么挑战?

使用并发编程需要面对上下文切换死锁资源限制等问题。

上下文切换

并发编程使用多线程来处理提高程序运行速度,但是并不是线程数越多,程序的运行速度就越快。线程数过多,反而可能会导致程序的运行速度会降低,这是因为多线程执行任务的时候会存在上下文切换的开销。(一个任务从保存到再加载的过程就是一次上下文切换。)

CPU是通过时间片轮询的方式来分配线程执行任务的时间。当一个线程执行完一个时间片之后,CPU会被分配给下一个分配到时间片的线程。

以单核计算机为例:计算机只有一个处理器可以分配,程序的线程数越多,上下文带来开销越大。这反而可能导致程序运行速度的下降。

如何减少上下文切换?

我们可以通过无锁并发编程CAS算法使用最少线程协程来减少上下文的切换。

  • 无锁并发编程:多线程竞争锁的时候,就会导致上下文的切换。使用多线程处理数据的时候,可以用一些方法避免锁的使用。例如:将数据的id按hash算法取模分段,使不同线程处理不同段的数据。
  • CAS算法:Java的Atomic包使用CAS算法来更新数据,不使用锁。
  • 使用最少线程:避免创建不需要的线程。
  • 协程:在单线程里面实现任务的调度,并完成多个任务之间的切换。

死锁

锁是个很有用的工具,但使用不当可能会导致死锁。

如何避免死锁?

  • 避免在一个线程里面同时获取多个锁。
  • 避免在一个锁里同时占用多个资源。
  • 对于数据库锁,加锁和解锁必须在同一个数据库连接里,否则可能出现解锁失败的情况。
  • 尝试使用定时锁。使用lock.tryLock(timeout)来替代使用内部锁机制。

资源限制的挑战

什么是资源限制?

资源限制是指在并发编程中,程序的运行速度受限于计算机硬件资源或软件资源。

如何解决资源受限的问题?

对于硬件资源,可以使用集群并行执行程序。

对于软件资源,可以使用资源池将资源复用。比如使用连接池将数据库和Socket连接复用。

在资源限制情况下进行并发编程?

在资源受限的情况下,如何让程序执行的更快?方法就是,根据不同的资源限制调整程序的并发度。