Java多线程

日常开发中我们常常需要使用到多线程来充分利用cpu实现高效执行,这其中需要我们多线程的执行和线程安全有充分的了解,本文主要围绕相关问题展开。

线程的状态集

Java线程有五种状态:

  1. 创建(new): 当刚创建线程对象并没有启动线程时
  2. 等待(waitting):此时线程处于对象的等待队列中,线程释放CPU,等待被唤醒,此时线程不会被分配CPU,常见于Object.wait(), Thread.join()方法调用后。
  3. 阻塞(blocked):此时线程因为没有获得对象同步锁而进入同步队列中,等待其他线程释放对象锁。常常是当一个线程从等待队列中被唤醒后,由于由于没有获得锁而进入阻塞状态。
  4. 运行(running):线程在此状态下开始运行或者等待CPU执行
  5. 结束(terminated): 线程结束

线程安全

线程安全是指多线程访问时,保证操作的可见性、有序性、原子性。之所以有会存在不安全的情况,是因为线程的工作模型是基于工作内存+主内存结构。

上述主内存可以大致理解为堆内存/磁盘,工作内存可以大致理解为虚拟机栈相关内存或者寄存器/高速缓存,Java线程执行时,先从主内存将共享数据拷贝到工作内存(线程私有),然后执行相关指令。那么各线程在工作内存操作数据时就会出现和主内存不一致的情况,导致出现奇怪的结果。

那么如何实现线程安全呢?

volatile变量

volatile变量有以下两条语义:

  1. 保证此变量对所有变量可见,即其他线程修改变量之后,当前线程可以立即得知。但是其并不能保证操作的原子性,即如果操作不是原子性的,那么仍然不是线程安全的。
  2. 插入同步栅栏,保证栅栏前后的指令在执行优化时不会重排序。
synchronized

synchronized基于互斥同步来保证可见性、原子性、有序性。即通过在字节码中插入moniterenter和moniterexit指令来使得只有获得了对象锁的线程才能执行当前代码块,而其他线程则必须等待当前锁释放后才能执行。

ReentrantLock

ReentrantLock是java并发包提供的线程安全工具类,其相比synchronized有以下优势

  1. 其等待可以被中断
  2. 公平锁:当多个线程在等待同一个锁时,必须按照申请时间顺序来依次获得锁
  3. 能在一个ReentrantLock对象上绑定多个Condition对象,能和多个条件关联。、

ReentrantLock其原理是AQS+CAS实现,CAS采用硬件保证操作的原子性,即先比较地址上变量的值是否满足预期,满足预期再将其更改为新的值。而在ReentrantLock中满足预期则表示当前线程拿到了锁,如果不满足,则将对象加入AQS队列,当其他线程释放释放后,再从AQS队列中取出等待对象,再次执行CAS。

线程模型

Java虚拟机屏蔽了各操作系统及其硬件层的差异,使得一套代码可以无缝在多个平台上运行,那么对于Java中的Thread与操作系统的线程的映射关系是如何的呢?

我们常规使用的Sun JDK的Window和Linux版本中都是使用一对一的线程模型来实现Java线程的,即一个Java Thread映射到一条轻量级进程中。

常见线程面试问题

  1. 谈谈你对AQS的理解lock和synchronized 区别

  2. 线程池如何知道一个线程的任务已经执行完成什么叫做阻塞队列的有界和无界

  3. lock和Synchronized 区别

  4. 讲一下wait和notify这个为什么要在synchronized 代码块中?你是怎么理解线程安全问题的?

  5. 什么是守护线程,它有什么特点谈谈你对AQS的理解

  6. AbstractQueuedSynchronized为什么采用双向链 表lock和synchronized 区别

  7. 线程池如何知道一个线程的任务已经执行完成什么

  8. ConcurrentHashMap底层具体实现知道吗?实现原 理是什么?能谈一下CAS机制吗?

  9. 死锁的发生原因和怎么避免

  10. volatile关键字有什么用?它的实现原理是什么?

  11. 请说一下ReentrantLock的实现原理?

  12. 基于数组的阻塞队列ArrayBlockingQueue原理怎么 理解线程安全?

相关推荐
让学习成为一种生活方式2 分钟前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
晨曦_子画8 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
Black_Friend16 分钟前
关于在VS中使用Qt不同版本报错的问题
开发语言·qt
南宫生31 分钟前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY40 分钟前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
残月只会敲键盘41 分钟前
php代码审计--常见函数整理
开发语言·php
xianwu54341 分钟前
反向代理模块
linux·开发语言·网络·git
Heavydrink44 分钟前
HTTP动词与状态码
java
ktkiko111 小时前
Java中的远程方法调用——RPC详解
java·开发语言·rpc
计算机-秋大田1 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue