Java 并发编程

Java 并发编程

前言

并发编程可以总结为三个核心问题:

  1. 分工:高效拆解任务并分配给线程
  2. 同步:线程之间的合作
  3. 互斥:同一时刻只允许一个线程访问共享资源。

分工、合作、不抢打印机。

Java SDK 并发包很大部分内容都是按照这三个维度组织的,如:

  1. Fork/Join 框架就是一种分工模式。
  2. CountDownLatch 就是一种典型的同步方式。
  3. 可重入锁 就是一种互斥手段。

Java SDK 并发包不过是针对并发问题开发出来的解决问题的工具。

Java SDK 并发包其余部分则是:并发容器、原子类。(辅助工具)

问题背后的本质、起源,站在理论、模型的角度来看Java并发问题。这些问题可以用于其它语言。

怎么学好?

  1. 跳出来,看全景。
  2. 钻进去,看本质。

1. 跳出来,看全景

建立一张全景图

并发编程抽象成三个核心问题:

  1. 分工
  2. 同步
  3. 互斥

1.分工

Java SDK 并发包里的 Executor 、 Fork/Join、Future 本质上都是一种分工方法。

并发编程领域还总结了一些设计模式:生产者/消费者、Thread-Per-Message、Worker Thread模式。

2.同步

线程间的协作问题。

一个线程执行完了一个任务,如何通知执行后续任务的线程开始。

Java SDK 并发包里的 Executor 、 Fork/Join、Future 本质上都是一种分工方法,同时也能解决线程间协作的问题。

Java SDK 中的 CountDownLatch、CyclicBarrier、Phaser、Exchanger也是用来解决线程协作问题的。

线程协作问题都可以描述为:

  1. 当某个条件不满足时,线程需要等待。
  2. 当某个条件满足时,线程需要被唤醒执行。

Java 并发编程领域,解决协作问题的核心技术是管程

管程是一种解决并发问题的能用模型。

管程是解决并发问题的万能钥匙。

这部分内容的学习,关键是理解管程模型。

3.互斥

分工、同步主要强调的是性能,并发编程还有一个问题需要关注:正确性。专业术语叫“线程安全”。

导致不确定性问题的原因是:

  1. 可见性问题
  2. 有序性问题
  3. 原子性问题

为了解决三个问题,Java语言引入了内存模型,内存模型提供了一系列的规则,利用这些规则,我们可以避免可见性问题,有序性问题,但还不足以完全解决线程安全问题。

解决线程安全问题的核心方案还是互斥。

互斥:指同一时刻,只允许一个线程访问共享变量(一个人使用打印机)。

实现互斥的核心技术就是锁, Java语言中的 synchronized、SDK里的各种Lock都能解决互斥问题。

虽然解决了安全性问题,但同时也带来了性能问题。

怎么保证安全性的同时,又尽可能提高性能呢?

可以分场景优化,Java SDK里提供的 ReadWriteLock、StampedLock 就可以优化读多写少场景下锁的性能。还可以使用无锁的数据结构,例如Java SDK里提供的原子类都是基于无锁技术实现的。

还有一些其它的方案,原理是不共享变量或者变量只允许读。这方面,Java提供了Thread Local和final 关键字,还有一种 Copy-on-write 的模式。

使用锁,除了注意性能问题,还需要注意死锁问题。

理解可见性:需要了解一些CPU和缓存的知识
理解原子性:需要理解一些操作系统的知识
无锁算法的实现:需要理解CPU缓存的知识

在这里插入图片描述

2. 钻进去,看本质

工程上的解决方案,一定要有理论做基础。

总结

并发知识要成体系的学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值