synchronize关键字和线程可见性

2024-01-23 12:20

本文主要是介绍synchronize关键字和线程可见性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

synchronize关键字

synchronize 锁定的对象分别为:方法锁、静态代码块锁、静态方法锁,而锁的范围跟锁对象的生命周期息息相关。而锁对象的其实是按照生命周期来判断,分别为对象锁和类锁

  • 类锁: 也就是class类,class类在jvm运行后便加载到了jvm的方法区中,一般情况下类锁的生命周期是跟着jvm的运行产生关系
  • 对象锁: 也就是对象的实例,根据对象的生命周期,如果对象的实例的内存地址

mark word

在hotsport虚拟机中,存储一个对象分为三部分:对象头、对象体、对齐填充。而java的每一个对象都是object的子类,在object对象的底层包含了很多本地的信息,其中包括mark word的信息。mark word记录了锁的相关信息并保存在了对象头中,mark word的大小根据jvm的位数进行动态调整,而mark word在对象头的存储数据图如下
在这里插入图片描述

锁的基本情况

在java1.6之前增加synchronize关键字一般都是直接通过调用系统底层的阻塞来完成的,并且把其他等待线程挂起操作。
在java1.6之后对synchronize进行了优化加入了偏向锁,轻量级锁

  • 偏向锁:偏向锁其实是一种无锁化的操作,适应于只有一个线程访问的时候,通过对象头中记录的threadID和epho来判断当前线程是获取线程的是哪个是否已经偏向,通过CAS(乐观锁)的方式来对threadID进行修改。如果存在多个线程咋进行锁升级->轻量级锁,该情况比较少,可以通过jvm参数关闭偏向锁
  • 轻量级锁:轻量级锁是偏向锁的升级,也是一种无锁化的操作,他通过自旋锁来操作,自旋也就是for循环通过自旋一定的次数或者自适应来判断是否升级锁,自适应是在jvm中判断上次获取锁的自旋的次数来动态决定下次获取锁的次数。如果通过自旋以后还是没有获取锁对象,则进行锁膨胀为->重量级锁,也就是java1.6之前的锁。
  • 重量级锁:重量级锁是通过monitor,每一个java对象都会有一个monitor,当一个线程获取锁以后,会调用monitorenter的指令,在线程完成后调用monitorexit的指令(释放锁),monitor依赖于底层系统的互斥锁来完成的

wait

在monitor中维护了两个队列,一个是synchronize队列,用户存放等待锁的想吃,还有一个是wait队列,当类调用了wait的时候回释放当前锁,然后把当前线程存放到monitor的wait队列中,只有调用了notify的时候才唤醒wait队列的数据,把数据迁移到synchronize队列中去竞争锁。

volatile和HappenBefore

在java层面一般使用volatile来解决可见性和有序性的问题。在java底层提供了四种指令内存屏障:storestore,loadload,storeload,loadstore,在使用volition关键字的时候回使用storeload来使修改的时候在其他线程可见。
happenBefore 是一种规则:

  • 在一个线程中的任何一个操作都应该happenbefore于该线程的任意后续操作之中
  • volatile变量规则,对于volatile关键字修饰的写的操作一定happenbefore于后续volatile变量的读的操作
  • 传递性规则:如果A happenbefore B, B happenbefore C,C happenbefore D,那么A happenbefore D,
  • start规则,在线程start以前的所有操作都happenbefore 与线程执行的所有操作
  • join规则,如果线程A 调用 B.join成功,那么线程b的所有操作都早于线程a从b调用成功之后
  • 监视器规则,对于任何一个获取synchronize锁的线程的所有操作都早于后一个获取synchronize锁的线程

这篇关于synchronize关键字和线程可见性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/636391

相关文章

Java线程池核心参数原理及使用指南

《Java线程池核心参数原理及使用指南》本文详细介绍了Java线程池的基本概念、核心类、核心参数、工作原理、常见类型以及最佳实践,通过理解每个参数的含义和工作原理,可以更好地配置线程池,提高系统性能,... 目录一、线程池概述1.1 什么是线程池1.2 线程池的优势二、线程池核心类三、ThreadPoolE

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

JAVA transient 关键字作用详解

《JAVAtransient关键字作用详解》Java的transient关键字用于修饰成员变量,使其不参与序列化过程,通过自定义序列化方法,可以手动控制transient变量的序列化行为,本文给大... 目录一、transient关键字作用二、原理详解三、典型使用场景四、代码示例五、注意事项六、与 stat

深入理解Redis线程模型的原理及使用

《深入理解Redis线程模型的原理及使用》Redis的线程模型整体还是多线程的,只是后台执行指令的核心线程是单线程的,整个线程模型可以理解为还是以单线程为主,基于这种单线程为主的线程模型,不同客户端的... 目录1 Redis是单线程www.chinasem.cn还是多线程2 Redis如何保证指令原子性2.

C++实现一个简易线程池的使用小结

《C++实现一个简易线程池的使用小结》在现代软件开发中,多线程编程已经成为提升程序性能的常见手段,本文主要介绍了C++实现一个简易线程池的使用小结,感兴趣的可以了解一下... 在现代软件开发中,多线程编程已经成为提升程序性能的常见手段。无论是处理大量 I/O 请求的服务器,还是进行 CPU 密集型计算的应用

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

Java JUC并发集合详解之线程安全容器完全攻略

《JavaJUC并发集合详解之线程安全容器完全攻略》Java通过java.util.concurrent(JUC)包提供了一整套线程安全的并发容器,它们不仅是简单的同步包装,更是基于精妙并发算法构建... 目录一、为什么需要JUC并发集合?二、核心并发集合分类与详解三、选型指南:如何选择合适的并发容器?在多

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有