Java并发编程篇

Java并发编程

多线程

Java多线程的安全性

  • 原子性:atomic包和synchronized修饰。
  • 可见性:volatile和synchronized
  • 有序性:happens-before原则来确保有序性

线程的创建方式

  • 继承thread
  • 实现Runnable,用Runnable对象创建线程
  • 实现Callable与FutrueTask,用FutureTask对象创建线程
  • 线程池

线程停止运行方式

  • 异常法停止:线程引入interrupt()方法,在run()方法中判断interrupt()状态。抛出异常

  • 沉睡停止:先sleep,在interrupt()判断,抛出异常。

  • stop()暴力停止

  • 使用return停止线程:也是引用interrupt判断。return退出run方法

Java线程的状态

  • RUNNABLE 就绪状态
  • BLOCKED 等待锁
  • WAITING 等待另一线程
  • TIMED_WAITING 指定等待时间
  • NEW 线程创建,还未调用start方法
  • TEMINATED 终止状态

sleep和wait的区别

  • sleep是静态,任何线程都可以直接thread.sleep调用。wait得是,Object类的实例方法,必须通过对象调用。
  • sleep,sleep不会释放锁。wait会释放锁。
  • sleep等待时间结束后,线程自动就绪。wait得notify,或notifyall唤醒。

BLOCKED和WAITNG的区别

  • BLOCKED,是等待锁的释放。获取锁后就转为RUNNABLE.
  • WAITING,是认为设置的状态,需要用notify激活。

notify选择哪个线程?

notify唤醒的线程是任意的,依赖于具体的JVM。

JVM有很多实现,比较流行的是hotspot。hotspot是“先进先出”的顺序唤醒。

不同线程之间怎么通信

synchronized 和 volatile。

  • 用violate修饰共同能看见的字段。

  • 一,用静态变量当锁,用wait,notify机制等待释放锁。
    二,ReentrantLock,condition包替代synchronized。condition.await 类似 wait . signal 类似notify ,signalAll 类似 notifyAll

  • BlockingQueue 线程安全的队列。

线程间通信方式有哪些?

  • Object的wait notify notifyAll

  • Lock Condition:await,signal,signalAll

  • volatile

  • CountDownLatch。一个同步辅助类。
    一个计数器.CountDownLatch(int count)需要等待的线程数量。
    countDown:减少计数器
    await:等待,直到计数器为0.

  • CyclicBarrier。让一组线程互相等待,直到达到某个屏障。有些类似于CountDownLatch的相反操作。等待的线程到达一定数量,才集体唤醒。

  • Semaphore。计数信号量。用于控制同时访问某个共享资源的线程数。
    通过acquire获取许可,release方法释放许可。没有许可会被阻塞。

Synchronized和ReentrantLock的区别

  • Synchronized是JVM层面的内置锁。
    ReentrantLock是java.util.concurrent.locks包的一个类。

  • 简单场景用synchronized(语法简洁、异常安全)
    复杂并发用ReentrantLoc(可中断、超时锁、公平锁、多条件队列、定时锁)

  • Synchronized,wait,notify
    ReentrantLock ,lock ,unlock

synchronized 和 ReentrantLock 都是 Java 中提供的可重入锁:

  • 用法不同:synchronized 可用来修饰普通方法、静态方法和代码块,而 ReentrantLock 只能用在代码块上。
  • 获取锁和释放锁方式不同:synchronized 会自动加锁和释放锁,当进入 synchronized 修饰的代码块之后会自动加锁,当离开 synchronized 的代码段之后会自动释放锁。而 ReentrantLock 需要手动加锁和释放锁
  • 锁类型不同:synchronized 属于非公平锁,而 ReentrantLock 既可以是公平锁也可以是非公平锁。
  • 响应中断不同:ReentrantLock 可以响应中断,解决死锁的问题,而 synchronized 不能响应中断。
  • 底层实现不同:synchronized 是 JVM 层面通过监视器实现的,而 ReentrantLock 是基于 AQS 实现的。

Synchronized原理

synchronized是Java提供的原子性内置锁,这种内置的并且使用者看不到的锁也被称为监视器锁

使用Synchronized之后,会在同步的代码块加上monitorenter和monitorexit字节码指令。

执行monitorenter指令会尝试获取锁。如果对象没被加锁或获得了锁,锁的计数器+1。其他线程等待。执行monitorexit指令释放锁,锁的计数器-1。其他线程竞争锁。

Reentrantlock工作原理

ReentrantLock 的底层实现主要依赖于 AbstractQueuedSynchronizer(AQS)这个抽象类。AQS 是一个提供了基本同步机制的框架,其中包括了队列、状态值等。

  • 可中断性。在底层,ReentrantLock 使用了与 LockSupport.park() 和 LockSupport.unpark() 相关的机制来实现可中断性。
  • 设置超时时间。这是通过内部的 tryAcquireNanos 方法来实现的。
  • 公平锁和非公平锁。公平锁的意思是按照线程等待时间长到短来顺序获取锁。
    公平锁可以通过在创建 ReentrantLock 时传入 true 来设置,

Synchronized可重入锁原理

Synchronized可重入锁原理

线程请求锁,检查锁状态。

  • 如果锁状态是0,代表没占用,使用CAS操作将线程ID换成自己的线程ID。
  • 如果锁状态是不是0,代表锁被占用。如果是可重入锁,锁的线程ID是自己的就会重新获取锁,锁status+1。非重入锁,进入阻塞队列等。

释放锁时,

  • 可重入锁,每一次退出方法,将会status-1,直至为0,最后释放该锁。
  • 非重入锁的,线程退出方法,直接会释放该锁。

ReentrantLock锁可重入原理

和Synchronized锁类似。运用了一个锁计数器。

Synchronized锁升级原理


Java并发编程篇
http://example.com/2025/08/26/Java并发编程/
作者
Luogic
发布于
2025年8月26日
许可协议