Java并发之synchronized实现原理深入理解

Java并发之synchronized实现原理深入理解

概述

Java中,synchronized关键字是实现多线程同步的一种重要机制,可以让代码块以原子性、独占性执行。在并发编程中,对synchronized的理解非常重要。本文将深入讲解synchronized的实现原理,包括synchronized的底层实现、锁升级机制等方面。

synchronized的实现原理

Java语言规范通过“锁对象”的概念实现了synchronized关键字。在每个Java对象上都存在一个锁(也称为监视器),线程在执行synchronized块之前,必须先得到锁;在执行完synchronized块之后,会将锁释放。锁的实现通过JVM底层实现,具体步骤如下:

  1. 查找对象头:访问对象头(Object Header)中的Mark Word(标记字段)。
  2. 确定锁状态:根据Mark Word判断对象的锁状态。当对象锁处于初始状态时,表示锁是自由的;当对象被某一个线程锁定时,锁就处于"busy"状态,其他请求锁动作的线程则会被阻塞挂起等待
  3. 转换锁状态:如果当前线程没有获取到对象锁,则JVM需要让线程进入阻塞状态,等待抢占锁。如果当前线程获取到了锁,则JVM会将锁的状态改成“locked,并将请求锁的线程记为ownerThread”

锁升级机制

JVM采用的锁升级方式是轻量级锁 -> 重量级锁,这种方式被称为锁的膨胀,也称为锁的升级。锁的升级是为了在多并发场景下,保证线程安全,避免死锁,提高程序性能。具体步骤如下:

  1. 轻量级锁:首先,JVM会将对象的Mark Word复制到线程线程的栈帧中,自旋尝试去获取锁,如果最终自旋成功,则代表此段同步代码块是处于线程共享的,锁状态会转化为:locked,ownerThread记录的就是这个自旋成功的线程。
  2. 重量级锁:在自旋尝试获取锁失败的情况下,线程就会进入到重量级锁, 将该线程睡眠相应时间(该时间内不占据锁对象)。在‘睡眠后,该线程重新进入阻塞队列,争夺锁。

示例说明

下面通过两个代码示例来说明synchronized的使用及实现原理:

示例1

public synchronized void doSth() {
    for (int i = 0; i < 10; i++) {
        System.out.println("doSth");
        // 睡眠100毫秒,方便线程切换
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上述示例中,我们定义了一个方法doSth(),在方法级别上使用了synchronized关键字修饰该方法。这样的话,当线程执行doSth()方法的时候,会先尝试去获取this这个对象的锁,如果获取到了锁,则该线程会持有锁并执行方法体中的代码;否则,此时处于阻塞状态,等待其它线程释放锁,进而争夺锁。如果多个线程同时访问doSth()方法,会出现互斥现象,即同一时间只有一个线程可以执行doSth()方法。

示例2

public void doSth() {
    synchronized (this) {
        for (int i = 0; i < 10; i++) {
            System.out.println("doSth");
            // 睡眠100毫秒,方便线程切换
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例中,我们使用synchronized关键字加锁的形式来修饰代码块,而不再是方法级别。synchronized (this)表示该代码块锁住的同步对象是当前对象,即this,这样该代码块的锁对象就是this,相比于在方法级别上加锁,可以更为细粒度地控制锁对象,避免其他的线程过度等待。当线程访问该代码块的时候,也是先去获取this对象的锁。相比于在方法上直接使用synchronized关键字,代码块的使用更为灵活,但是需要自己维护好锁的释放和锁的获取,避免死锁等问题的发生。

总结

本文对synchronized的底层实现原理、锁升级机制做了详细的介绍,并结合实例进行了说明。对于Java并发编程的理解以及代码实现具有一定的借鉴作用。在实际开发中,应该根据实际需求来选择锁的实现方式并细致地处理好锁的获取和释放,提高程序的健壮性和性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java并发之synchronized实现原理深入理解 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • Go语言并发技术详解

    Go语言并发技术详解攻略 为什么要学习Go语言并发技术 Go语言是一款天生支持并发的编程语言,其强大的并发特性可以有效提升程序运行效率和性能。并发技术在现代化的应用程式中越来越重要,尤其是在大规模分布式系统中,用Go编写的应用程序往往能更好地处理高并发情况,提高系统的稳定性和可靠性。因此,学习Go语言并发技术对于Web开发、数据处理、高性能计算等领域的开发人…

    多线程 2023年5月16日
    00
  • Java中多线程的ABA场景问题分析

    Java中多线程的ABA场景问题分析 ABA场景问题简介 多线程中,如果一个线程在读取一个共享变量时,另一个线程把它修改为另外一个值,再修改回原来的值,这时第一个线程可能会检查到期望的值,但是并没有发现这个值已经被修改过,这种情况就叫做ABA场景问题。 ABA场景问题如何解决 Java中提供了一个原子变量类AtomicStampedReference来解决A…

    多线程 2023年5月16日
    00
  • Java多线程之同步工具类CountDownLatch

    当我们在开发多线程应用程序时,经常需要在等待某一些任务完成后再继续执行下去。Java中提供了多种同步工具类,包括CountDownLatch。 CountDownLatch是一个同步工具类,用于等待一个或多个线程执行完毕后再执行另一个或多个线程。CountDownLatch通过计数器来实现,计数器初始化为一个整数,当计数器为0时,另一个线程可以执行。 以下是…

    多线程 2023年5月17日
    00
  • Java多线程之FutureTask的介绍及使用

    Java多线程之FutureTask的介绍及使用 介绍 FutureTask是Java提供的一种异步计算结果的方式。它可以在一个线程中执行异步的计算,同时能够在另一个线程中获取计算结果。FutureTask实现了Future接口和Runnable接口,因此它可以被当做一个任务提交给ThreadPoolExecutor等线程池来执行。 使用 创建FutureT…

    多线程 2023年5月16日
    00
  • 详解C++ 共享数据保护机制

    详解C++ 共享数据保护机制攻略 什么是共享数据 共享数据是指多个线程同时访问同一数据,而且每个线程都可以修改数据。因为多个线程同时访问同一数据,所以需要额外的保护机制来避免数据竞争和错误的结果。 数据保护机制 常见的数据保护机制有: 1. 互斥锁(Mutex) 互斥锁是一种最常用的保护共享数据的方法,即通过加锁(lock)来保护共享数据。同一时间只有一个线…

    多线程 2023年5月17日
    00
  • Python异步爬虫多线程与线程池示例详解

    对于Python异步爬虫多线程与线程池示例的攻略,我将分成以下几个部分进行讲解: 简介:异步爬虫、多线程以及线程池的概念和作用 异步爬虫指的是利用异步编程模式来实现网站数据的爬取,可以大大提升程序的性能。而多线程和线程池则是更为常见的提高网络爬虫效率的手段。 多线程:通过使用多个线程来同时执行多个任务,以达到快速完成任务的效果。Python提供了多线程模块—…

    多线程 2023年5月17日
    00
  • Java并发编程进阶之线程控制篇

    Java并发编程进阶之线程控制篇 Java并发编程是指在多线程执行的情况下管理程序的执行流程和资源共享。线程控制是Java并发编程重要的一个方面,本篇攻略将帮助您学习Java中线程的创建和控制。 线程创建 Java中线程的创建有两种方式:继承Thread类和实现Runnable接口。 通过继承Thread类创建线程 继承Thread类 重写run方法 创建并…

    多线程 2023年5月16日
    00
  • 详解python多线程之间的同步(一)

    这里我将详细讲解“详解python多线程之间的同步(一)”的完整攻略。 标题:详解python多线程之间的同步(一) 前言 多线程是Python中一个非常重要的概念,它可以帮助我们更好的利用计算机的资源,提高程序的执行效率。但是多线程的并发操作会带来一些问题,比如线程之间的同步。本文就主要讲解Python多线程之间的同步问题。 同步的概念 在多线程中,当两个…

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部