Java并发编程学习笔记1

230 阅读3分钟

线程的优势

如果使用得当,线程可以降低开发和维护成本提高复杂应用程序的性能。线程通过将异步工作流转变为几乎线性工作流,可以更轻松地模拟人类的工作和交互方式。他们还可以将原本复杂的代码转换为更易于编写、阅读和维护的线性代码。

利用多处理器

由于调度的基本单位是线程,只有一个线程的程序一次最多只能在一个处理器上运行。在双处理器系统上,单线程程序放弃了对一半可用 CPU 资源的访问;在 100 个处理器的系统上,它放弃了 99% 的访问权限。另一方面,具有多个活动线程的程序可以在多个处理器上同时执行。如果设计得当,多线程程序可以通过更有效地利用可用的处理器资源来提高吞吐量。

使用多线程还有助于在单处理器系统上实现更好的吞吐量。

简化建模

与同时管理多种不同类型任务的程序相比,按顺序处理一种类型任务的程序更易于编写、不易出错且更易于测试。

简化异步处理

如果每个请求都有自己的线程,那么阻塞不会影响其他请求的处理。

响应更快的GUI

线程的风险

安全隐患

线程安全性可能出乎意料地微妙,因为在缺乏足够同步的情况下,多个线程中的操作顺序是不可预测的。

递增符号 someVariable++ 可能看起来是一个单一的操作,但实际上是三个独立的操作:读取值,将其加一,然后写出新值。由于多个线程中的操作可能会被运行时任意交错,因此两个线程可能会同时读取该值,都看到相同的值,然后都将其加一。结果是从不同线程中的多个调用返回相同的序列号。

UnsafeSequence 说明了一种称为竞态条件的常见并发危险。当从多个线程调用时,getNext 是否返回唯一值(如其规范所要求的那样)取决于运行时如何交错操作——这不是理想的状态。

安全版本代码:

活性隐患

顺序程序中可能发生的一种活性失败形式是无意的无限循环,其中循环后面的代码永远不会执行。线程的使用引入了额外的活性风险。例如,如果线程 A 正在等待线程 B 独占占有的资源,而 B 从未释放它,则 A 将永远等待。

性能隐患

在设计良好的并发应用程序中,线程的使用是一种净性能增益,但线程仍然会带来一定程度的运行时开销。上下文切换——当调度程序暂时挂起活动线程以便另一个线程可以运行时——在具有许多线程的应用程序中更频繁,并且具有显着的成本:保存和恢复执行上下文、局部性丢失以及 CPU 时间花在调度线程上而不是线程运行上。

对线程安全的需求并不仅限于框架调用的组件——它扩展到访问这些组件所访问的程序状态的所有代码路径。因此,对线程安全的需求是具有传染性的。