目录
2.1 什么是多线程并发编程
- 并行是说在单位时间内多个任务同时在执行。
- 并发是指同一个时间段内多个任务同时都在执行,并且都没有执行结束。
- 并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行。
在多线程编程实践中,线程的个数往往多于 CPU 的个数,所以一般都称多线程并发编程而不是多线程并行编程。
2.2 为什么要进行多线程并发编程
多核 CPU 时代的到来打破了单核 CPU 对多线程效能的限制。多个 CPU 意味着每个线程可以使用自己的 CPU 运行,这减少了线程上下文切换的开销,但随着对应用系统性能和吞吐量要求的提高,出现了处理海量数据和请求的要求,这些都对高并发编程有着迫切的需求
2.3 Java 中的线程安全问题
- 线程安全问题是指当多个线程同时读写一个共享资源并且没有任何同步措施时,导致出现脏数据或者其他不可预见的结果的问题。
- 如果多个线程都只是读取共享资源而不去修改,那么就不会存在线程安全问题,只有当至少一个线程修改共享资源时才会存在线程安全问题。
2.4 Java 中共享变量的内存可见性问题
- Java 内存模型规定,将所有的变量都存放在主内存中,当线程使用变量时,会把主内 存里面的变量复制到自己的工作空间或者叫作工作内存,线程读写变量时操作的是自己工作内存中的变量。Java 内存模型是一个抽象的概念。
- 现实中线程的工作内存是一个双核 CPU 系统架构,每个核有自己的控制器和运算器,其中控制器包含一组寄存器和操作控制器,运算器执行算术逻辑运算。每个核都有自己的一级缓存,在有些架构里面还有一个所有 CPU 都共享的二级缓存。那么 Java 内存模型里面的工作内存,就对应这里的 L1 或者 L2 缓存或者 CPU 的寄存器。但是线程之间可能会出现共享变量的内存不可见。
2.5 Java 中的 synchronized 关键字
synchronized 关键字介绍
关键字 synchronized 在线程访问共享变量时可以进行适当的同步,解决线程安全问题
- synchronized 块是 Java 提供的一种原子性内置锁,Java 中的每个对象都可以把它当作 一个同步锁来使用,这些 Java 内置的使用者看不到的锁被称为内部锁,也叫作监视器锁。
- 线程的执行代码在进入 synchronized 代码块前会自动获取内部锁,这时候其他线程访问该同步代码块时会被阻塞挂起。
怎么释放该内置锁?
- 拿到内部锁的线程会在正常退出同步代码块或者抛出异常后或者在同步块内调用了该内置锁资源的 wait 系列方法时释放该内置锁。
- 内置锁是排它锁, 也就是当一个线程获取这个锁后,其他线程必须等待该线程释放锁后才能获取该锁。
synchronized 的内存语义
- 共享变量内存可见性问题主要是由于线程的工作内存导致的,这个内存语义就可以解决共享变量内存可见性问题。
- 进入 synchronized 块的内存语义是把在 synchronized 块内使用到的变量从线程的工作内存中清除,这样在 synchronized 块内使用到该变量时就不会从线程的工作内存中获取,而是直接从主内存中获取。
- 退出 synchronized 块的内存语义是把在 synchronized 块内对共享变量的修改刷新到主内存。
- 除可以解决共享变量内存可见性问题外,synchronized 经常被用来实现原子性操作。 但synchronized 关键字会引起线程上下文切换并带来线程调度开销,因为synchronized 是独占锁,没有获取内部锁的线程会被阻塞掉,会引起线程上下文切换并带来线程调度开销。
2.6 Java 中的原子性操作
- 原子性操作是指执行一系列操作时,这些操作要么全部执行,要么全部不执行,不存在只执行其中一部分的情况。如果不能保证执行过程是原子性的,那么就会出现线程安全问题。
怎么保证多个操作的原子性呢?
使用 synchronized 关键字进行同步,以实现线程安全性,即内存可见性和原子性,


324

被折叠的 条评论
为什么被折叠?



