写点什么

JVM 如何实现线程同步,干货精讲

用户头像
Android架构
关注
发布于: 18 小时前

Java 编程语言的优势之一是它支持语言级的多线程。大部分支持都集中在协调对多个线程之间共享的数据的访问。


JVM 将正在运行的 Java 应用程序的数据存放到多个运行时数据区域中:一个或多个 Java 堆栈,堆和方法区。


在 JVM 内部,每个线程都被分配一个虚拟机栈,其中包含其他线程无法访问的数据,包括线程调用的每个方法的局部变量,参数和返回值。虚拟机栈上的数据仅限于基本类型和对象引用。在 JVM 中,无法将实际对象的存放在虚拟机栈上,所有对象都分配在堆上。


JVM 中只有一个,并且所有线程都共享它。堆只包含对象。无法在堆上分配单独的原始类型或对象引用 - 这些东西必须是对象的一部分。数组也分配在堆上,包括基本类型的数组,但在 Java 中,数组也是对象。


除了虚拟机栈和堆之外,还有方法区,它包含程序使用的所有类(或静态)变量。方法区域类似于堆栈,因为它只包含基本类型和对象引用。但是,与虚拟机栈不同,方法区域中的类变量由所有线程共享。


  • 对象和类锁



如上所述,JVM 中的两个存储区包含所有线程共享的数据。这些是:


  • 堆,包含所有对象

  • 方法区域,包含所有类变量


如果多个线程需要同时使用相同的对象或类变量,则必须很好的控制对数据的访问。否则,程序将出现不可预测的问题。


为了协调多个线程之间的共享数据访问,Java 虚拟机将锁与每个对象和类相关联。锁就像一个特权,任何时候只有一个线程可以“拥有”。如果线程想要锁定特定对象或类,它会询问 JVM。在线程向 JVM 发出锁定之后 JVM 会为线程提供锁定。当线程不再需要锁时,它会将锁归还给 JVM。如果另一个线程请求了相同的锁,则 JVM 将锁传递给另外一个线程。


类锁在实现上为对象锁。当 JVM 加载类文件时,它会创建一个类实例java.lang.Class。锁定类时,实际上是锁定该类的Class对象。


线程无需获取锁来访问实例或类变量。但是,如果一个线程确实获得了一个锁,那么没有其他线程可以访问锁定的数据,直到拥有该锁的线程释放它为止。

监视器

JVM 将锁与监视器结合使用。监视器相当于是监护人,它监视一系列代码,确保一次只有一个线程执行代码。


每个监视器都与对象引用相关联。当线程到达监视器监视下的代码块中的第一条指令时,线程必须获取对引用对象的锁定。在获得锁之前,不允许线程执行代码。一旦获得锁定,线程就会进入受保护代码块。


当线程离开块时,无论它如何离开块,它都会释放相关对象的锁定。

多个锁

允许单个线程多次锁定同一对象。对于每个对象,JVM 维护对象被锁定的次数。解锁对象的计数为零。当线程第一次获取锁定时,计数增加到 1。每次线程获取对同一对象的锁定时,计数都会递增。每次线程释放锁定时,计数都会递减。当计数达到零时,锁被释放并可供其他线程使用。

同步块

在 Java 语言术语中,必须访问共享数据的多个线程的协调称为同步。该语言提供了两种内置方式来同步对数据的访问:使用 synchronized 语句或同步方法。

同步语句

要创建 synchronized 语句,请使用synchronized带有表达式的关键字,该表达式的计算结果为对象引用,如reverseOrder()下面的方法所示:


class KitchenSync {private int[] intArray = new int[10];void reverseOrder() {synchronized (this) {int half


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


Way = intArray.length / 2;for (int i = 0; i < halfWay; ++i) {int upperIndex = intArray.length - 1 - i;int save = intArray[upperIndex];intArray[upperIndex] = intArray[i];intArray[i] = save;}}}}

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
JVM如何实现线程同步,干货精讲