JVM-默背版

1.JVM对sychronized的优化:锁膨胀、锁消除、锁粗化、自适应自旋锁

(1)锁膨胀:从无锁、偏向锁、轻量级锁、重量级锁的过程叫做锁膨胀。在JDK1.6以前,sychronized是由重量级锁实现的,加锁和解锁的过程需要从用户态切换到内核态,性能低下。有了锁膨胀机制,大多数场景可以使用无锁、偏向锁和轻量级锁,在执行并发操作的时候,避免了线程从用户态到内核态,从而减少性能的开销。

(2)锁消除:JVM检测到代码段不再被共享和竞争,此时就会取消该代码段的所属的代码段。

(3)锁粗化:将多个连续的加锁、解锁操作链接在一起,形成一个范围更大的锁。

(4)自适应自旋锁:通过自身循环,获取锁的一种方式,避免了线程开启和线程挂起的性能开销。因为线程开启和线程挂起需要从用户态转到内核态,这个过程是比较缓慢的,性能比较低下。

2.介绍AQS

3.CAS和AQS的关系

4.用AQS实现可重入的公平锁

5.ThreadLocal的作用

6.乐观锁和悲观锁

7.java中实现乐观锁的方式

8.CAS的缺点

9.为什么不能所有的锁都用CAS

10.CAS有什么问题,java是如何解决的

11.volatile的作用

volatile可以保证可见性,不能保证原子性,所以会引发线程安全的问题。如果一个线程修改了使用volatile关键字的修饰的变量,其他线程也能获取到这个变量的最新值,从而避免了数据不一致的状态。

对于复合操作,比如i++这种自增操作,因为不是原子操作,如果有多个线程修改了i的值,volatile是不能保证线程安全的。需要用Sychronized和Lock来保证原子性和线程安全。

12.volatile和sychronized的比较

13.什么是公平锁和非公平锁。

14.非公平锁的吞吐量为什么比公平锁大。

15.reentrantlock是怎么实现公平锁的。

公平锁和非公平锁的区别是,公平锁中有hasQueueProcessors()=false方法,来看自己之前还有线程在排队吗

hasQueuedPredecessors() 用来判断 当前等待队列是否有线程在排队获取锁。对于非公平锁,无论是否已经有线程在排队,都会尝试获取锁,获取不到再排队。

tryLock()方法是非公平的,可以插队

16.线程池的核心参数

new SynchronousQueue<>() 是 Java 并发包 里的一个用法。SynchronousQueue 是 java.util.concurrent 提供的一种特殊的 阻塞队列。

和普通的队列(ArrayBlockingQueue、LinkedBlockingQueue)不同:它不存储任何元素,容量是 0。

每次 put() 必须等到有另一个线程 take(),才能成功;反过来 take() 也必须等到有人 put()。

所以它其实是一个 线程之间直接移交(handoff)数据的工具。

把 SynchronousQueue 想象成 过手交易:

线程 A 想交给线程 B 一个包裹。

A 必须等到 B 伸手来拿(调用 take()),才能把东西放出去。

它不像普通队列能"先存进去,等别人慢慢取"。



17.await()方法

(1)Condition.await()

在 java.util.concurrent.locks.Condition 接口中,await() 是用来 让当前线程等待,直到其他线程通过 signal() 或 signalAll() 唤醒它。常用场景是自定义锁下的线程等待/通知机制。

java 复制代码
import java.util.concurrent.locks.*;

public class AwaitExample {
    private static final Lock lock = new ReentrantLock();
    private static final Condition condition = lock.newCondition();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread t1: Waiting...");
                condition.await(); // 等待被唤醒
                System.out.println("Thread t1: Woke up!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        Thread t2 = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("Thread t2: Sleeping for 2s...");
                Thread.sleep(2000);
                condition.signal(); // 唤醒等待的线程
                System.out.println("Thread t2: Sent signal!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}

await() 会释放锁并让当前线程等待。

signal() 或 signalAll() 会唤醒等待线程。

与 Object.wait() 类似,但更灵活,可以在 Lock 中使用。

(2)CountDownLatch.await()

在 java.util.concurrent.CountDownLatch 中,await() 是 阻塞当前线程,直到计数器为 0。

java 复制代码
CountDownLatch latch = new CountDownLatch(3);

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName() + " finished work");
        latch.countDown(); // 计数器减 1
    }).start();
}

latch.await(); // 阻塞,直到计数器为 0
System.out.println("All threads finished!");

(3)CompletableFuture.await()(类似概念) 不常用

在 异步编程里,比如在某些库或 Kotlin/JavaScript 的 async/await 中,await 用来 等待异步操作完成并获取结果。Java 标准库里 CompletableFuture 没有 await() 方法,但可以用 get() 或 join() 实现类似效果。

java 复制代码
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
String result = future.join(); // 等待结果
System.out.println(result); // 输出 "Hello"

18.例子3

join() → 一直等,直到目标线程结束。

前面例子里写的 t1.join(); t2.join(); 的意思就是:

主线程会先等待 t1 执行结束,再等待 t2 执行结束,最后才继续往下走。这样可以确保两个子线程都跑完。

假设两个线程并发读写同一个整型变量,初始值为零,每个线程加 50次,结果可能是什么?

在没有任何同步机制的情况下,两个线程并发对同一个整型变量进行 50 次加1操作,最终结果可能是100,也可能小于 100,最坏的结果是 50,也就是最终的结果可能是在 [50,100]。

小于 100 情况的分析,由于对整型变量的 num++ 操作不是原子操作,它实际上包含了三个步骤:读取变量的值、将值加 1、将新值写回变量。在多线程环境下,可能会出现线程安全问题。例如,线程1和线程2同时读取了变量的当前值,然后各自将其加 1,最后都将相同的新值写回变量,这就导致了一次加 1操作的丢失。这种情况会多次发生,最终结果就会小于 100。

java 复制代码
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerAddition {

        private static AtomicInteger num = new AtomicInteger(0);

        public static void main(String[] args) throws InterruptedException{
            Thread thread1 = new Thread(()->{
                for(int i=0;i<50;i++){
                    num.incrementAndGet();}
            });
            Thread thread2 = new Thread(()-> {
                for(int i=0;i<50;i++){
                    num.incrementAndGet();
                }
            });
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println("最终结果:"+ num.get());


        }

}

通过sychronized方法,保证操作的互斥性。

java 复制代码
public class SynchronizedAddition {
    private static int num =0;
    private static final Object lock = new Object();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(()-> {
            for(int i=0;i<50;i++){
                synchronized(lock){
                    num++;
                }
                }
            });
                Thread thread2 = new Thread(()-> {
                    for (int i = 0; i < 50; i++) {
                        synchronized (lock) {
                            num++;
                        }
                    }
                });
                        thread1.start();
                        thread2.start();
                        thread1.join();
                        thread2.join();
                        System.out.println("最终结果:"+ num);

                    }
                }
相关推荐
Dovis(誓平步青云)7 小时前
《探索C++11:现代语法的内存管理优化“性能指针”(下篇)》
开发语言·jvm·c++
星梦清河8 小时前
宋红康 JVM 笔记 Day14|垃圾回收概述
jvm·笔记
小鸡脚来咯8 小时前
一个Java的main方法在JVM中的执行流程
java·开发语言·jvm
江团1io08 小时前
深入解析三色标记算法
java·开发语言·jvm
一枝花算不算浪漫8 小时前
线上频繁FullGC?慌得一比!竟是Log4j2的这个“特性”坑了我
jvm·后端
王伯安呢10 小时前
Java开发环境配置入门指南
java·开发语言·jvm·eclipse·环境搭建·新手
叙白冲冲19 小时前
JVM:程序计数器
jvm
DKPT19 小时前
JVM中如何调优新生代和老生代?
java·jvm·笔记·学习·spring
phltxy19 小时前
JVM——Java虚拟机学习
java·jvm·学习