java中synchronized锁的升级过程

Java中的synchronized锁是一种用于实现线程同步的机制,它可以保证在多线程环境下的数据同步和共享资源的安全访问。在使用synchronized锁的时候,我们需要注意其锁的升级过程,因为锁升级过程直接影响着程序的性能和效率。

一、synchronized锁的升级过程

synchronized锁的升级过程可以分为三种状态,分别是无锁状态、偏向锁状态和重量级锁状态。下面详细讲解每种状态:

  1. 无锁状态

在未经过任何同步操作的情况下,对象处于无锁状态,此时线程是可以直接访问该对象的成员变量和成员方法的。

  1. 偏向锁状态

如果只有一个线程直接进行加锁和解锁操作,那么就会出现偏向锁状态。在偏向锁状态下,锁会记录下持有偏向锁的线程ID,以后该线程访问同步块的时候就可以直接使用偏向锁而不需要再次操作同步机制。如果有其他线程访问该同步块,则会撤销偏向锁,升级为轻量级锁。

  1. 重量级锁状态

如果存在多个线程争夺同一个对象并且使用synchronized关键字进行加锁操作,那么就会出现重量级锁状态。在重量级锁状态下,锁会使用操作系统的互斥量来完成同步机制。当一个线程获取锁时,其他线程必须等待获得锁的线程释放锁后才能再次去争夺锁。

二、synchronized锁的升级过程示例

为了更好地理解synchronized锁的升级过程,下面给出两个示例,分别是偏向锁和重量级锁状态的示例。

  1. 偏向锁状态示例
public class SynchronizedDemo {

    private static final int COUNT = 1_0000_0000;
    private static Lock lock=new ReentrantLock();
    private static int num = 0;

    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        T1 t1 = new T1();

        lock.lock();
        while (--COUNT > 0) {
            num++;
        }
        lock.unlock();
        t1.start();
        t1.join();
        System.out.println("num:" + num);
        System.out.println(System.currentTimeMillis() - start);
    }

    private static class T1 extends Thread {

        @Override
        public void run() {
            lock.lock();
            num += 10;
            lock.unlock();
        }
    }
}

在这个示例中,主线程通过一个循环对变量num进行了多次累加操作,在执行完成后启动了一个子线程t1,t1线程的任务是对变量num进行加10操作。由于主线程对num进行了多次操作,因此这个场景无法完全满足偏向锁的条件,实际运行过程中也没有出现偏向锁状态,所有的操作都是重量级锁状态。

  1. 重量级锁状态
public class SynchronizedDemo {

    private static final int COUNT = 1_0000_0000;
    private static int num = 0;

    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        T1 t1 = new T1();

        synchronized (SynchronizedDemo.class) {
            while (--COUNT > 0) {
                num++;
            }
        }
        t1.start();
        t1.join();
        System.out.println("num:" + num);
        System.out.println(System.currentTimeMillis() - start);
    }

    private static class T1 extends Thread {

        @Override
        public void run() {
            synchronized (SynchronizedDemo.class) {
                num += 10;
            }
        }
    }
}

在这个示例中,主线程对变量num进行多次累加操作的过程中使用了synchronized关键字,此时锁的状态为重量级锁,t1线程对num进行加10操作时,同样需要操作synchronized关键字,线程会被阻塞直到获得锁。

三、总结

如上述示例所示,在使用synchronized锁的过程中,应尽量减少线程之间对同一个对象的竞争,越少的竞争会带来更好的程序性能。同时,我们还需要注意synchronized锁的升级过程,尽量使线程的操作在偏向锁或者轻量级锁状态下完成,避免进入重量级锁状态,从而提高程序的效率。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java中synchronized锁的升级过程 - Python技术站

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

相关文章

  • springboot集成schedule实现定时任务

    下面是springboot集成schedule实现定时任务的完整攻略: 1. 学习前提 在学习本篇攻略之前,需要掌握以下基础知识: Java基础语法 Spring框架基础知识 SpringBoot框架基础知识 2. Schedule简介 Schedule是Spring框架提供的一种任务调度框架,用于在指定的时间间隔内执行指定的任务。Schedule有以下几种…

    Java 2023年5月15日
    00
  • jsp、struts、spring、mybatis实现前端页面功能模块化拆分的方案

    要理解如何使用JSP、Struts、Spring和MyBatis实现前端页面功能模块化拆分的方案,需要遵循以下步骤: 确定需要拆分的功能模块 首先,您需要确定哪些功能模块可以拆分成独立的组件。这可以通过查看您的应用程序并确定哪些部分可以在不同的页面或功能区域中重用来实现。 例如,您的网站可以拆分为登录、注册、个人资料和搜索等功能模块。 创建独立的JSP文件和…

    Java 2023年5月20日
    00
  • JSP中c:foreach遍历和s:iterator遍历异同实例分析

    JSP中有两种常用的集合遍历方式:c:foreach和s:iterator。它们都可用于遍历Java集合对象,但在使用上有一些异同点。 c:foreach遍历 c:foreach是JSTL的核心标签库之一,提供了一种简化集合遍历的方法。它的语法如下: <c:forEach var="item" items="${colle…

    Java 2023年6月15日
    00
  • JDBC连接MYSQL分步详解

    JDBC连接MYSQL分步详解 JDBC是Java Database Connectivity的缩写,表示Java数据连接,是一种标准的Java API。JDBC提供了跨多种数据库管理系统的连接协议,能够让Java程序通过这套协议与数据库进行交互,从而实现对数据的增删改查操作。 本文将详细介绍如何使用JDBC连接MYSQL数据库,包括以下几个步骤: 下载安装…

    Java 2023年5月19日
    00
  • Java连接数据库oracle中文乱码解决方案

    下面是关于Java连接数据库Oracle中文乱码解决方案的攻略,分为以下几个步骤: 1. 确定数据库字符集和Java字符集 在连接Oracle数据库前,首先需要确定Oracle数据库的字符集和Java程序的字符集是否一致。可以通过以下方式来确认: 查看Oracle数据库字符集 在Oracle数据库中执行以下SQL语句来查看数据库的字符集: SELECT * …

    Java 2023年5月20日
    00
  • Java实现简单的分页功能

    下面是“Java实现简单的分页功能”的完整攻略。 第一步:引入相关依赖 在项目的pom.xml文件中引入以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa&…

    Java 2023年5月26日
    00
  • jsp利用echarts实现报表统计的实例

    让我为您详细讲解“jsp利用echarts实现报表统计的实例”的完整攻略。 1. 环境准备 运用 ECharts 前,需要先引入核心库文件 echarts.min.js。因此,我们需要进行以下操作:- 下载 ECharts:从 ECharts 官网(https://echarts.apache.org/zh/download.html)下载最新版 EChar…

    Java 2023年6月15日
    00
  • Java 分位点(分位值)计算方式

    当需要将一组数据进行分布分析时,可以通过计算分位点(quantile),常用的分位点有中位数、上四分位数、下四分位数等。在Java中,可以使用Apache Commons Math库来计算分位点,本文将介绍Java分位点计算方式的完整攻略。 引入依赖 要使用Apache Commons Math库,需要在pom.xml文件中添加以下依赖: <depen…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部