Java Concurrencyin Practice 并发编程实践系列1

Java Concurrencyin Practice 并发编程实践

《Java Concurrency in Practice》是于2006年出版,由Brian Goetz等人合著的一本经典的Java并发编程指南。该书详细介绍了Java平台上的并发编程概念、技术和最佳实践。它提供了丰富的实例和案例研究,帮助开发人员理解和解决并发编程中的常见问题。至今仍然被广泛认可为Java并发编程领域的经典参考书籍之一。

让我们看看17年前的前辈们对并发的理解与实践。

preface

在preface这里大概描述了这本书的由来,因许多工程师随着并发量的提高,从而不断涌现出bug,在2004年java发布java.util.concurrent包,并在2006年针对并发问题,著作了这本书。

At this writing, multicore processors are just now becoming inexpensive enough for midrange desktop systems. Not coincidentally, many development teams are noticing more and more threading-related bug reports in their projects. In a recent post on the NetBeans developer site, one of the core maintainers observed that a single class had been patched over 14 times to fix threading-related problems. Dion Almaer, former editor of TheServerSide, recently blogged (after a painful debugging session that ultimately revealed a threading bug) that most Java programs are so rife with concurrency bugs that they work only “by accident”.

越来越多的开发团队在项目中遇到与线程相关的错误报告。

这导致开发、测试和调试多线程程序变得异常困难,因为并发错误往往无法可预测地显现,而且往往在最糟糕的时候出现,比如在生产环境下、在负载较重时。

大多数 Java 程序都充斥着并发 bug,它们仅仅是“碰巧”可以工作。

Indeed, developing, testing and debugging multithreaded programs can be extremely difficult because concurrency bugs do not manifest themselves predictably. And when they do surface, it is often at the worst possible time—in production, under heavy load.

由于并发性的 bug 不会以可预见的方式自己“蹦”出来,因此多线程程序的开发、测试和调试都会变得极端困难。bug 浮出水面的时刻,通常可能是最坏的时候一一对应于生产环境,就是指在高负载的时候。

One of the challenges of developing concurrent programs in Java is the mismatch between the concurrency features offered by the platform and how developers need to think about concurrency in their programs. The language provides low-level mechanisms such as synchronization and condition waits, but these mechanisms must be used consistently to implement application-level protocols or policies. Without such policies, it is all too easy to create programs that compile and appear to work but are nevertheless broken. Many otherwise excellent books on concurrency fall short of their goal by focusing excessively on low-level mechanisms and APIs rather than design-level policies and patterns.

使用Java 开发并发程序所要面对的挑战之一,是要面对平台提供的各种并发特性之间的不匹配,还有就是程序员在他们的程序中应该如何思考并发性。语言提供了一些低层机制,比如同步和条件等待,但是这些机制在实现应用级的协议与策略时才是必须的。不顾这些策略的约束,很容易创建出一个程序,它在编译和运行时看上去一切正常,不过这其中却存在隐患。很多并发方面相当不错的书都没能达到预期的目标,它们过分地关注于低层的机制和API,而不是设计层面的策略和模式。

Java 5.0 is a huge step forward for the development of concurrent applications in Java, providing new higher-level components and additional low-level mechanisms that make it easier for novices and experts alike to build concurrent applications. The authors are the primary members of the JCP Expert Group that created these facilities; in addition to describing their behavior and features, we present the underlying design patterns and anticipated usage scenarios that motivated their inclusion in the platform libraries.

Our goal is to give readers a set of design rules and mental models that make it easier—and more fun—to build correct, performant concurrent classes and applications in Java.

We hope you enjoy Java Concurrency in Practice.

Brian Goetz

Williston, VT

March 2006

Java 5.0 是在使用Java 开发并发应用程序的进程中,迈出的巨大一步。它提供了新的高层组件以及更多的低层机制,这些将使得一名新手更容易像专家那样去构建并发应用程序。本书的作者都是JCP 专家组的主要成员,正是这个专家组创建了这些新工具:除了去描述新工具的行为和特性,我们还向您展示了它们低层的设计模式,预期的使用场景以及将它们纳入平台核心库的动机。
我们的目标是给读者一些设计法则和理念模型,让读者在使用 Java 构建正确、高效的并发类和应用程序时,变得更容易、更有趣。

Java 5.0 java.util.concurrent

在网上说java.util.concurrent的很多,在什么时候引入就很少介绍, 后面我自己在外网搜了下。

Java的并发工具包(java.util.concurrent)是在Java 5版本中引入的。

Java 5发布于2004年,它引入了许多新的语言特性和库,其中包括了用于并发编程的java.util.concurrent包。

java.util.concurrent包提供了一组并发编程工具和类,用于简化多线程编程和管理并发任务。它包含了诸如线程池(ThreadPoolExecutor)、并发集合(ConcurrentHashMap、ConcurrentLinkedQueue等)、原子变量(AtomicInteger、AtomicLong等)、倒计时门闩(CountDownLatch)等常用的并发构件。这些工具和类的引入使得开发人员能够更方便地编写高效且线程安全的并发代码。

Java的并发工具包的引入极大地改善了并发编程的可用性和可靠性,提供了更高级别的抽象和更强大的工具,使开发人员能够更好地处理并发编程的挑战。这也为后续的Java版本奠定了并发编程的基础,并成为开发高性能和可伸缩性应用程序的重要工具之一。

在java5 之后一些并发编程方面的重要更新

  • Java 6:在Java 6中,对并发工具包进行了一些改进和优化。添加了诸如ConcurrentSkipListMap、ConcurrentSkipListSet和TransferQueue等新的并发集合类。此外,还引入了可重入锁(ReentrantLock)的公平性设置以及Condition条件变量的支持。
  • Java 7:Java 7引入了一些新的并发特性,例如Fork/Join框架,用于高效处理分而治之的并行任务。此外,还添加了Phaser类,用于线程间的同步协作。
  • Java 8:Java 8引入了函数式编程的特性,并在并发编程方面进行了一些增强。添加了CompletableFuture类,用于更方便地处理异步任务和回调。还引入了新的并行流(Parallel Streams)功能,以便更容易地将顺序操作转换为并行操作。
  • Java 9:Java 9在并发编程方面引入了一些新的改进,包括改进的锁实现、改进的并发集合类和更好的并发编程工具支持。

第一章 Introduction 并发介绍

1.1 A (very) brief history of concurrency

作者回顾了计算机行业的发展历程,从早期的单核处理器到现在的多核处理器,解释了为什么并发编程成为当代软件开发的重要议题。

作者提到早期的计算机系统中通常只有一个处理器,因此并发编程并不是一个主要的关注点。然而,随着处理器技术的发展和硬件成本的下降,多核处理器变得越来越普及,使得并发编程成为必要的技能。

作者还提到,并发编程的出现是为了充分利用多核处理器的性能,并发编程的目标是使程序能够同时执行多个任务,并充分利用系统资源。

1.2 Benefits of threads

本节着重强调了使用线程进行并发编程的益处,并介绍了几个与线程相关的优势。

首先,使用线程可以提高程序的响应性。通过将任务分配给不同的线程并同时执行,程序可以更快地响应用户的请求,提供更好的用户体验。

其次,线程可以提高系统的吞吐量。通过并行处理多个任务,系统能够同时执行多个操作,从而提高整体处理能力。

此外,线程还可以更好地利用多核处理器的资源。在多核系统中,使用线程可以充分利用每个核心的处理能力,提高系统的性能。

本节还提到了一些其他的线程优势,例如更好的资源利用、更容易的任务管理和更高的可扩展性。

1.2.3 Simplified handling of asynchronous events

在这节中,提到了synchronous I/O, nonblocking I/O 和 multiplexed I/O(多路复用)。

In a single-threaded application, this means that not only does processing the corresponding request stall, but processing of all requests stalls while the single thread is blocked. To avoid this problem, singlethreaded server applications are forced to use nonblocking I/O, which is far more complicated and error-prone than synchronous I/O.

作者提到在单线程应用中,意味着不仅处理对应请求停止了,处理所有的请求都停止了,当单线程被锁住的时候。而避免这个问题,单线程应用 被迫使用的 非锁住的IO流,这个更复杂和更容易出错 对比同步IO流。

However, if each request has its own thread, then blocking does not affect the processing of other requests.

这里最后提到的每个请求拥有自己的线程的模型是一种常见的处理方式,被称为(one-thread-per-request)模型。在这种模型中,每个请求都会被分配一个独立的线程进行处理,不同请求之间的处理互不影响。如果一个请求发生阻塞,只会影响到该请求对应的线程,而不会影响其他请求的处理。

然而,随着应用程序规模的增大和并发需求的增加,使用"one-thread-per-request"的模型可能会导致线程数量过多,占用大量系统资源,同时线程切换的开销也会增加。这种模型在高并发情况下可能面临线程资源耗尽、上下文切换开销过大等问题。

现代的并发编程模型和框架通常采用了更高效的方式来处理请求,如使用线程池来重用线程、使用异步非阻塞的I/O模型等。这样可以更好地利用系统资源,减少线程创建和销毁的开销,提高并发处理能力。

因此,现在的实践中,不一定每个请求都有自己的线程。相反,更常见的做法是使用线程池来管理一定数量的线程,通过线程池来处理请求。这样可以更好地控制线程的数量,避免线程过多导致的资源浪费,并且通过异步非阻塞的方式处理I/O操作,提高系统的并发性能。

后面,针对

1.3 Risks of threads

主要写了线程带来的风险和挑战,包括以下几个方面:

  1. Safety hazards: 线程间共享数据可能导致数据竞争和并发访问的安全问题。并发访问共享数据时,如果没有正确地进行同步和互斥操作,可能导致数据不一致或者出现意外的结果。

  2. Liveness hazards: 线程间的相互依赖和资源竞争可能导致死锁、活锁和饥饿等问题。死锁指的是多个线程因相互等待对方释放资源而无法继续执行;活锁指的是线程在不断重试导致无法取得进展;饥饿指的是某个线程因无法获取所需的资源而一直无法执行。

  3. Performance hazards: 线程的创建和上下文切换会带来一定的开销,如果过度使用线程可能导致系统性能下降。同时,线程间的竞争和同步操作也可能引入额外的开销。

  4. Scalability hazards: 多线程的并发编程需要考虑系统的可扩展性。如果设计不当,过多的线程可能导致系统资源耗尽、上下文切换开销过大等问题,限制了系统的可扩展性和并发性能。

  5. Debugging and testing hazards: 并发程序的调试和测试更加困难,由于并发bug不易预测和重现,需要更加谨慎地进行测试和调试,以确保程序的正确性和稳定性。

这章也会在后面着重讲解,对并发编程来说非常重要。

1.4 Threads are everywhere

这一章节主要强调了线程在现代计算中的普遍存在性和重要性。

  1. 线程的广泛应用:现代计算中的几乎所有领域都使用了线程,包括操作系统、服务器、桌面应用程序、移动应用程序、游戏和嵌入式系统等。线程的使用使得程序能够同时执行多个任务,提高了系统的并发性和性能。
  2. 用户界面响应性:在用户界面的开发中,线程的使用至关重要。通过将用户界面的操作放在单独的线程中,可以确保用户界面的响应性,防止阻塞用户操作的情况发生。
  3. 并发编程挑战:尽管线程在提高系统性能和响应性方面有很大的优势,但并发编程也带来了一些挑战。线程之间的同步、竞争条件、死锁和活锁等问题都可能导致程序的错误行为和性能问题。
  4. 基于任务的编程模型:现代并发编程趋向于使用基于任务的编程模型,即将程序划分为多个独立的任务,并通过线程池等机制来执行这些任务。这种模型简化了并发编程,并提供了更好的可伸缩性和性能。
  5. 并发性的未来:随着计算机系统变得更加复杂和并发,对并发编程的需求也越来越高。并发性将继续是软件开发的重要领域,需要不断发展新的技术和工具来简化并发编程,并提供更好的性能和可靠性。

总的来说,本章强调了线程在现代计算中的普遍应用,并指出了并发编程所面临的挑战和发展趋势。了解并掌握并发编程的原理和技术对于开发高性能和可靠的软件系统至关重要。

总结

该书详细介绍了Java平台上的并发编程概念、技术和最佳实践。它提供了丰富的实例和案例研究,帮助开发人员理解和解决并发编程中的常见问题。

该书的内容主要分为四个部分:

第一部分介绍了并发编程的基础知识和背景

  • 探讨了并发编程的挑战、线程安全性、共享对象、对象的构造和发布、线程封闭性等概念。此部分还介绍了Java中用于构建并发应用程序的基本机制,如线程、锁、条件等。

第二部分深入讨论了共享对象的可变性

  • 涵盖了原子性、可见性和有序性等概念,并介绍了Java中的原子类、volatile关键字和显式锁等工具。此部分还讨论了常见的并发问题,如竞态条件、死锁、饥饿和活跃性问题,并提供了解决这些问题的技巧和模式。

第三部分介绍了并发编程的高级主题

  • 包括线程池、执行器框架、同步容器类、并发工具类、非阻塞算法等内容。此部分还讨论了性能优化、性能测试和调试技术,以及如何设计并发应用程序。

第四部分涵盖了一些特殊的并发主题

  • 如并发集合、原子变量、显式锁、同步器和并发编程的最佳实践等。此外,该书还提供了一些示例代码和实际应用的案例研究,以帮助读者更好地理解并发编程的概念和技术。

《Java Concurrency in Practice》被广泛认为是学习和实践Java并发编程的权威参考。它提供了全面而深入的内容,涵盖了从基础知识到高级技术的方方面面。无论是初学者还是有经验的Java开发人员,都可以从中获得宝贵的知识和实践经验,从而提升自己在并发编程领域的能力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小大凳子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值