`

Java多线程高并发进阶篇(二)-synchronized实现原理剖析

阅读更多

在多线程并发编程中,线程安全是关注的重点。一般来说,使用多线程编程是为了获得更高的执行效率,如果连最基本的数据准确性都无法保证,那么谈论并发就没有任何意义。

一.为什么说同步锁(synchronized锁)是重量级锁?

在谈到高并发多线程编程中,估计大家接触到最多的就是synchronized,它在并发编程中是一个元老级别的角色。我们把synchronized锁(同步锁)称为重量级锁,是因为它会导致争用不到锁的线程阻塞,而阻塞或者唤醒一个线程就需要操作系统介入,并且需要在用户态和内核态之间转换,而这个转换过程需要花费大量的资源(因为用户态和内核态都有自己各自的内存空间,在状态切换过程中,用户态需要将参数变量等内容发送给内核态,而内核态需要记录用户态在切换过程的状态)。

 

二.同步锁的实现原理

在说实现原理之前,我们需要知道同步锁的实现基础:每一个Java对象都可以作为锁!为什么这么说?我们先来点基础内容。

1.根据同步锁的作用范围,可以把同步锁分为:

①对象锁:对给定的对象加锁,在进入代码块之前需要获取此对象的锁。

②实例锁:作用于类中的实例方法,锁是当前实例对象。

③类锁:作用于类中的静态方法,锁是当前类的Class对象。

 

我们先来一小段代码,看下它的字节码。

 

public class SynchronizedDemo {
	Object object = new Object();
	public void testObjectLock() {
		synchronized (object) {
				System.out.println("对象锁");
	    }
	}
	
	public synchronized void testInstanceLock() {
		System.out.println("实例锁");
	}
	
	public static synchronized void testClassLock() {
		System.out.println("类锁");
	}
}

 

我们看一下对象锁在字节码中的表现形式。


 在字节码中,我们发现了一对monitorenter和monitorexit指令。

对了,对象锁的同步实现就是使用monitorenter和monitorexit指令实现的,而实例锁和类锁是使用另外一种方式实现的,细节在JVM规范里并没有详细说明,但是可以明确的是实例锁肯定也可以使用此方式实现。

 

2.我们在JVM规范中关于这两指令的描述,一探究竟:

JVM规范关于monitorenter 写道 
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
• If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
• If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
• If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.

我们解释下这段话(大家可以借助谷歌翻译),对于monitorenter 解释如下:

每个锁对象都与一个监视器相关联。 当监视器被占用时,就会处于被锁定状态。 当有线程执行monitorenter指令时,会尝试获取与锁对象关联的监视器的所有权,过程如下所示:

①如果与锁对象关联的监视器的计数器值为0,则线程获取监视器的所有权,并将监视器的计数器值设置为1。 

②如果线程已经拥有了与锁对象关联的监视器,那么它将重新进入监视器(也就是重新获取监视器的所有权),然后将监视器的计数器值+1。

③如果另外一个线程已经拥有了与锁对象关联的监视器,则线程会阻塞,直到监视器的计数器值变为0,然后尝试获取所有权。

JVM规范关于monitorexit 写道
The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.

对于monitorexit解释如下: 

执行monitorexit指令的线程必须是锁对象对应的监视器的所有者。指令执行时,监视器的计数器数减1,如果减1后进入数为0,那线程退出监视器,不再是这个监视器的所有者。其他被这个监视器阻塞的线程可以尝试去获取这个监视器的所有权。 

 

从JVM的规范要求的实现描述中,我们可以看到,实现对象锁的方法就是使用monitorenter和monitorexit指令。

这也就解释了一句话:每一个对象都可以作为一个锁对象存在!

下一帖,我们介绍下锁的信息存储在哪,以及锁的升级(也叫膨胀)过程及对比。

  • 大小: 9.7 KB
分享到:
评论

相关推荐

    多线程精品资源--高并发-高可靠-高性能three-high-import导入系统-高并发多线程进阶.zip

    "多线程精品资源--高并发-高可靠-高性能three-high-import导入系统-高并发多线程进阶.zip" 这个压缩包文件名暗示了其内容可能包含了一系列关于如何在复杂系统中有效地利用多线程来达到高并发、高可靠性和高性能的...

    java多线程进阶

    这本书“java多线程进阶”显然旨在帮助读者深化这方面的理解,打通编程中的“任督二脉”,使开发者能够更加熟练地在并发环境中编写高效且稳定的代码。 1. **线程基础**:书中首先会介绍Java多线程的基础知识,包括...

    Java语言程序设计.进阶篇(原书第8版)

    1. **多线程编程**:Java是支持多线程的,理解如何创建和管理线程,以及如何处理并发问题,如死锁和竞态条件,是Java程序员必须掌握的技能。书中会详细解释`Thread`类和`Runnable`接口,以及如何使用`synchronized`...

    Java语言程序设计.进阶篇.原书第10版

    1. **多线程编程**:Java提供了内置的多线程支持,允许程序同时执行多个任务。书中会详细介绍Thread类和Runnable接口的使用,以及线程同步、互斥和死锁的概念,如synchronized关键字、wait()、notify()和notifyAll()...

    Java语言程序设计-进阶篇(原书第10版).pdf

    进阶篇会详细讲解如何创建和管理线程,使用守护线程,同步机制如`synchronized`关键字、`java.util.concurrent`包中的并发工具类,以及线程安全的数据结构。 2. **异常处理**:理解如何有效地使用异常处理机制,...

    Java语言程序设计-进阶篇(原书第8版)

    1. **多线程编程**:Java是并发编程的强大平台,书中会详细介绍Thread类和Runnable接口,如何创建并管理线程,以及如何使用同步机制(如synchronized关键字、wait()和notify()方法)避免线程安全问题。此外,还会...

    Java语言程序设计.进阶篇(原书第8版)中文版

    - **并发集合**:介绍Java并发包中专为多线程环境设计的集合类,如`ConcurrentHashMap`等,并给出具体使用示例。 #### 4. 并发编程 - **线程生命周期**:全面了解线程的状态变迁过程,包括创建、就绪、运行、阻塞、...

    [Java语言程序设计-进阶篇(原书第8版)]

    1. **多线程**:Java以其强大的多线程支持而闻名。书中会详细讲解如何创建和管理线程,包括同步机制(如synchronized关键字、wait/notify、Lock接口)、线程池(ExecutorService)以及并发集合等。 2. **网络编程**...

    Java语言程序设计-进阶篇

    2. **同步机制**:为了保证多线程环境下的数据一致性,Java提供了多种同步机制,如`synchronized`关键字、`ReentrantLock`等。 3. **线程池**:通过使用线程池可以有效地管理和复用线程资源,避免频繁创建和销毁线程...

    《Java语言程序设计(进阶篇)》 课后习题第27章代码chapter27.rar

    1. **多线程编程**:Java是多线程编程的强大平台,可能包括线程的创建、同步、死锁以及线程池的使用等。线程同步机制如`synchronized`关键字、`wait()`、`notify()`和`notifyAll()`方法,以及`Lock`接口和`...

    java进阶篇主要内容的PPT

    **Java进阶篇主要内容概述** 本PPT详细阐述了Java进阶学习的关键概念和技术,旨在帮助读者深化对Java编程的理解,提升开发技能。这个资料涵盖了不仅限于教科书的知识,确保你能够掌握到实际工作中可能遇到的实用...

    架构师进阶之路-Java架构致力于提供后端工程师提供架构设计相关的各种资源和面试题 .zip

    1. **Java基础**: 作为后端工程师,扎实的Java基础知识是必不可少的,包括但不限于语法、面向对象编程、异常处理、集合框架(如ArrayList、LinkedList、HashMap等)、多线程、I/O流、反射、序列化等。 2. **设计...

    《Java语言程序设计(进阶篇)》 课后习题第30章代码chapter30.rar

    1. **Java并发处理**:在Java中,多线程是提高程序效率的关键技术。可能的习题会涉及`Thread`类的使用、同步机制(如`synchronized`关键字)、`wait()`, `notify()`和`notifyAll()`方法,以及`ExecutorService`和`...

    java语言程序设计提高篇+进阶篇第十版

    1. **多线程编程**:Java以其强大的并发支持而闻名。书中深入讨论了线程的创建、同步机制(如synchronized关键字、wait/notify机制和Lock接口)、线程池的使用,以及如何避免常见的并发问题。 2. **集合框架**:...

    Java进阶高手课-并发编程透彻理解

    接着,课程将深入探讨Java内存模型(JMM),讲解volatile、synchronized以及final关键字的作用,这些都是保证多线程环境下数据一致性的重要机制。同时,还会讲解到原子性操作和Lock接口,如Atomic类和ReentrantLock...

    Java进阶学习资料.zip

    2. 多线程:掌握并发编程的基础,包括线程的创建、同步与通信(synchronized、wait/notify、Lock接口)以及并发容器如ConcurrentHashMap和BlockingQueue。 3. 设计模式:学习并实践23种经典设计模式,如工厂模式、...

    《Java语言程序设计(进阶篇)》课后习题第19章代码chapter19.rar

    《Java语言程序设计(进阶篇)》课后习题第19章主要涉及的是Java高级编程的一些核心概念和技术,包括但不限于多线程、网络编程、I/O流、集合框架的深入理解和应用。这一章的代码示例是帮助学生巩固理论知识并提升...

    北大计算机系JAVA培训讲义(进阶篇)

    1. **多线程**:Java提供了丰富的多线程支持,包括Thread类和Runnable接口,以及synchronized关键字、volatile变量、Lock接口等同步机制。学习者将了解如何创建和管理线程,以及如何处理并发问题,如死锁、活锁和...

Global site tag (gtag.js) - Google Analytics