并发编程:从理论到实践
1. 并发编程中的数据处理挑战
在并发编程里,我们常常要面对诸多数据处理方面的难题。当读取数据时,我们得留意读到的究竟是最新的有效数值,还是缓存里遗留的旧值。同时,要保证对变量的修改是原子性的,防止线程看到部分修改的情况。而且,还得保护多个线程,避免它们同时修改数据。
对于处理可变数据的应用程序而言,每一次对共享可变状态的访问都必须确保正确无误。只要有一处出错,整个应用程序就可能崩溃。实际上,很多并发的 Java 应用程序都存在问题,只是我们尚未察觉。
不过,如果使用 final
(不可变)字段引用一个不可变实例,让多个线程访问它就不会有隐藏问题。任何线程都能读取该值,首次访问时会在本地缓存中获取一份副本。由于值是不可变的,后续从本地缓存访问该值就足够了,还能获得不错的性能。所以,共享可变性是个大问题,我们要尽量避免。
那如果不能改变任何东西,应用程序又如何运作呢?我们可以围绕共享不可变性来设计应用程序。具体有以下几种方法:
- 封装可变状态 :将可变状态封装好,只共享不可变数据。
- 函数组合 :像纯函数式语言那样,让所有数据都不可变,通过函数组合实现功能。在这种方式下,我们进行一系列转换,从一个不可变状态过渡到另一个不可变状态。
- 使用监控库 :借助一个库来监控数据的变化,一旦有违规情况就发出警告。
2. 并发编程的重要性与传统模型问题
无论是开发交互式客户端桌面应用程序,还是后端高性能服务,并发编程都起着关键作用。