博客
关于我
promise.all是并发执行吗_攻破面试灵魂拷问,解读Java并发编程的艺术,本文带你深入l理解...
阅读量:796 次
发布时间:2023-03-04

本文共 3933 字,大约阅读时间需要 13 分钟。

前言

欢迎关注头条号:Java小野猫

最近好多朋友都在为了升职,涨薪,跳槽,忙得焦头烂额。我们都知道,升职加薪的过程充满了挑战,尤其是面试环节。为了能进入自己理想的公司,必须付出努力。今天,我为大家分享的是Java核心知识点系列中的《Java并发编程》。这本书是一本电子书,由于篇幅限制,我无法全面分享全部内容。但是,如果你对这方面感兴趣,可以私信我【资料】,我会提供下载链接。

这本书主要聚焦于Java并发编程的核心知识点,是面试中的必问内容。由于篇幅限制,我只能分享部分内容。如果需要更详细的内容,可以自行获取。希望这份分享对你有所帮助。

目录

以下是本书的目录,您可以根据需要选择阅读:

适读对象

适合以下读者阅读:

  • Java开发工程师
  • 架构师
  • 并发编程爱好者
  • 开设相关课程的大专院校师生

阅读本书之前,建议具有一定的Java基础和开发经验,最好还有一定的并发编程经验。如果你是并发编程的新手,可以按照章节顺序进行学习,并结合实例进行编码实战。如果你已经有一定的并发编程经验,可以将本书当作参考手册,直接阅读需要的章节。

一、并发编程的挑战

并发编程虽然能提高程序效率,但也伴随着许多挑战。在实际开发中,如何高效、稳定地实现并发编程是每个开发者需要面对的难题。本章将介绍并发编程的几个关键挑战,以及如何应对这些挑战。

1.1 上下文切换

CPU通过时间片分配算法支持多线程执行。尽管是单核处理器,也能通过切换线程执行,让我们感受不到延迟。时间片通常只有几十毫秒,因此上下文切换虽然频繁,但延迟却很小。然而,这种切换会影响程序的效率。下面的代码可以帮助你理解并发与串行的时间差。

public class ConcurrencyTest {

private static final long count = 10000L;

public static void main(String[] args) throws InterruptedException {

concurrency();

serial();

}

private static void concurrency() throws InterruptedException {

long start = System.currentTimeMillis();

Thread thread = new Thread(new Runnable() {

@Override

public void run() {

int a = 0;

for (long i = 0; i < count; i++) {

a += 5;

}

}

});

thread.start();

int b = 0;

for (long i = 0; i < count; i++) {

b--;

long time = System.currentTimeMillis() - start;

thread.join();

System.out.println("concurrency :" + time + "ms,b=" + b);

}

private static void serial() {

long start = System.currentTimeMillis();

int a = 0;

for (long i = 0; i < count; i++) {

a += 5;

int b = 0;

for (long i = 0; i < count; i++) {

b--;

long time = System.currentTimeMillis() - start;

System.out.println("serial:" + time + "ms,b=" + b + ",a=" + a);

}

}

测试结果显示,并发执行并不一定比串行执行快,具体取决于任务的类型和线程数量。尽管并发可以提高吞吐量,但同时也增加了复杂性,容易引发问题。

1.2 死锁

锁是一种强大的同步工具,但如果不正确使用,可能会导致死锁。例如,两个线程可能在等待对方释放锁的情况下长时间卡住。这种情况通常发生在一个线程获取锁后,未能及时释放锁,导致另一个线程无法继续执行。开发中需要注意锁的正确使用,避免出现死锁问题。

本章小结

本章主要介绍了并发编程中的几个关键挑战,包括上下文切换和死锁。并发编程虽然能提高程序效率,但也需要谨慎处理,避免因不正确的并发控制而引发问题。对于Java开发者来说,建议在开发中尽量使用JDK提供的并发包工具,如线程池、锁和原子操作等,这些工具经过充分优化,能够更好地应对并发编程中的挑战。

二、Java并发机制的底层实现原理

在Java中,并发编程离不开内核机制。本章将深入探讨Java中的并发机制,包括volatile、synchronized和原子操作的实现原理,以及它们在实际开发中的应用。

2.1 volatile的应用

volatile是Java中用于多线程编程的关键修饰符,它保证了共享变量的可见性。在多核处理器环境下,volatile变量的实现涉及到CPU的缓存一致性机制。以下是volatile的定义及其在硬件层面的实现原理。

Java语言规范第3版对volatile的定义是:为了确保共享变量能被准确和一致地更新,线程应该通过排他锁来访问该变量。Java提供了volatile修饰符,在某些场景下比锁更方便。通过volatile变量,Java线程内存模型确保所有线程看到该变量的值是一致的。

在了解volatile的实现原理之前,我们先来看一下与其相关的CPU术语。表2-1是CPU术语的定义:

表2-1:CPU术语定义

volatile是如何在硬件层面上实现可见性的?让我们通过X86处理器的JIT编译器生成的汇编代码来分析。以下是包含volatile变量的Java代码及其对应的汇编代码:

Java代码如下:

转换成汇编代码如下:

从汇编代码可以看出,volatile变量的写操作会执行Lock前缀指令。这一指令有两个作用:首先,将当前处理器缓存行的数据写回系统内存;其次,确保其他CPU缓存中该内存地址的数据无效。这保证了多线程环境下共享变量的可见性和一致性。

2.2 synchronized的实现原理与应用

synchronized是Java中实现同步的关键工具,它通过锁机制保证线程的互斥性。然而,synchronized在性能上有一定的代价。在Java SE 1.6中,synchronized被优化为轻量级锁和偏向锁,以减少锁的获取和释放带来的性能消耗。本文将详细介绍synchronized的实现原理及其优化方式。

Java中的每一个对象都可以作为锁,其锁的类型包括:

  • 普通同步方法:锁是当前实例对象
  • 静态同步方法:锁是当前类的Class对象
  • 同步方法块:锁是Syncronized括号内的对象

锁的存储结构和升级过程是synchronized实现同步的基础。JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。代码块同步使用monitorenter和monitorexit指令实现,而方法同步则使用另外一种方式。不过,两种同步方式都可以通过这两个指令来实现。

2.2.1 Java对象头

Java对象头包含了多个信息,包括Mark Word、Klass、GC标记位、引用类型等。其中,Mark Word字段在synchronized和volatile操作中起到了关键作用。它用来记录锁的状态和偏向锁的信息。

2.2.2 锁的升级与对比

为了提高锁的获取和释放效率,Java SE 1.6引入了偏向锁和轻量级锁。锁的状态从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。锁一旦升级到轻量级锁或重量级锁,就不能再降级。这一机制通过减少锁的竞争和等待时间,提高了并发程序的性能。

1.偏向锁

偏向锁是针对单线程竞争的优化。在大多数情况下,锁不会被多个线程竞争。为了减少这种单线程竞争带来的开销,引入了偏向锁。持有偏向锁的线程在进入和退出同步块时,不需要再次竞争锁,可以直接进行操作。

2.轻量级锁

如果出现多线程竞争,轻量级锁会迅速升级为重量级锁,以减少自旋带来的CPU浪费。自旋指的是在获得锁的线程被阻塞的情况下,继续去竞争锁的行为。为了避免无用的自旋,一旦锁升级为重量级锁,就不会再恢复到轻量级锁状态。

2.3 原子操作的实现原理

原子操作是并发编程中的核心要素。在多处理器环境下,原子操作需要通过特殊的硬件支持来确保操作的原子性。Intel处理器通过专用指令实现原子操作的支持。以下是原子操作的实现原理及其在Java中的应用。

在Intel处理器中,原子操作的实现依赖于专用的FPU(浮点数处理单元)和MMU(内存管理单元)。通过这些硬件结构,原子操作能够在多处理器环境下保证操作的原子性和一致性。Java中的原子操作类(如AtomicInteger、AtomicLong)利用这些硬件机制来实现高效的并发操作。

本章小结

本章深入探讨了Java并发机制的底层实现原理,包括volatile、synchronized和原子操作的实现细节。这些机制是Java并发编程的基石,了解它们的实现原理有助于更好地利用Java的并发工具类进行并发编程。

读者福利

由于篇幅限制,我只能分享本书的部分内容。如果你对并发编程感兴趣,或者需要进一步学习相关知识,可以通过私信我【资料】获取完整电子书。希望这份分享能为你的学习之路提供一些帮助。

转载地址:http://crxfk.baihongyu.com/

你可能感兴趣的文章
Postman学习之常用断言
查看>>
postman居然是用electron开发的,我们来认识下这个框架吧
查看>>
postman常用公共函数
查看>>
Postman常见问题及解决方法
查看>>
PostMan怎样携带登录信息请求后台接口防止出现无法访问资源问题
查看>>
Postman接口传参案例
查看>>
postman接口功能测试
查看>>
Postman接口测试
查看>>
Postman接口测试
查看>>
Postman接口测试/接口自动化实战教程
查看>>
Postman接口测试之POST、GET请求方法
查看>>
Postman接口测试之Post、Get请求方法
查看>>
Postman接口测试之:添加Cookie伪造请求
查看>>
Postman接口测试企业级实战
查看>>
PostMan接口测试实战
查看>>
Postman接口测试实战讲解
查看>>
Postman接口测试工具安装部署与快速入门
查看>>
postman接口测试常见问题
查看>>
postman接口测试,1个参数有好几个值的时候如何测试比较简单快速?
查看>>
Postman接口测试:配置token为全局变量,配置测试环境
查看>>