java中synchronized关键字基础-1
1、synchronized关键字简介
synchronized是java中的一个关键字,在中文中为同步,也被称之为'同步锁',以此来达到多线程并发访问时候的并发安全问题,可以用来修饰代码块、非静态方法。静态方法等;
修饰代码块时:给当前指定的对象加锁
修饰非静态方法时:作用于当前实例加锁
修饰静态方法时:作用于当前类对象加锁
synchronized在java内存模型中的主要作用
原子性:通过monitorenter和monitorexit指令,保证被synchronized修饰的代码在同一时间只能被一个线程访问,在锁未释放之前,无法被其他线程访问到
可见性:保证共享变量的修改能够及时可见,对一个变量的unlock操作之前,必须把此变量同步回主内存中(store和write操作)
有序性:一个变量在同一时刻只允许一条线程对其执行lock操作,这条规则决定了持有同一个锁的两个同步块只能串行执行
2、synchronized修饰代码块
当synchronized修饰代码块时,有以下几种情况
1、this关键字
synchronized(this){ //互斥代码 `` }
这里的this就是等价于调用这个方法的对象,synchronized锁的就是this这个对象的锁,若有多个对象调用方法,各个对象锁之间相互独立,互不影响
2、Class.class
synchronized(Test.class){ //互斥代码
} 这里synchronized锁的对象为类锁,在需要类锁的代码不能同时执行,但是与非需要类锁的对象锁或者与没有加锁的代码可以同时执行 用synchronized进行加锁时看获得锁是对象还是类的锁,还有的是synchronized锁住的是一个对象或者类(其实也是对象),而不是方法或者代码段。 3、synchronized修饰实例方法 public synchronized void method(){ //代码 }
当synchronized修饰实例方法时,锁的是该类的实例对象
4、synchronized修饰静态方法
public synchronized static void method() { // todo
`` }
由于static静态方法是属于类的而不属于对象的,所以synchronized修饰的静态方法锁定的是这个类的所有对象
5、synchronized的底层实现原理
在java内存模型中,synchronized可以保证原子性、有序性、可见性,在这之前,先谈谈对象在HotSpot虚拟机中的分布,主要有三部:对象头(Header)、实例数据(Instance Data)和对象填充(Padding)
对象头
对象头主要包括两部分信息,第一部分用于存储对象自身的运行时数据、如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,官方称之为'Mark Word',还有一部分称之为类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
存储内容标志位状态对象哈希码、对象分代年龄01未锁定指向锁记录的指针00轻量级锁定指向重量级锁的指针10膨胀(重量级锁定)空,不需要记录信息11GC标识偏向线程ID、偏向时间戳、对象分代年龄01可偏向
实例数据
实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。这部分的存储顺序会受到虚拟机分配策略参数(-XX: FieldsAllocationStyle) 和字段在Java源码中定义顺序的影响。
对齐填充
对齐填充并不是必然存在的,也没有特别的含义,仅仅只是起着占位符的作用,由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,就是对象的大小必须是8字节的整数倍,而对象头部分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。
原子性
synchronized实现原子性底层是通过JVM来实现的,同一时间只能有一个线程去执行synchronized中的代码块;
每一个对象都有一个监视器monitor来关联,监视器被占用时会被锁住,其他线程无法获取该monitor,当JVM执行某个线程的的内部方法的monitorenter,它会尝试去获取该对象的monitor的所有权,过程如下
1、若monitor的进入数为0,线程可以进入monitor,并将该monitor的进入数置为1,那么该线程就成为monitor的所有者
2、若线程已拥有monitor的所有权,允许它重入monitor,则进入monitor的进入数加1(recursions:记录线程拥有锁的次数)
3、若其他线程已经占有monitor的所有权,那么当前尝试获取monitor的所有权的线程会被阻塞,直到monitor的进入数变为0,才能重新尝试获取monitor的所有权。
monitorexit指令
1、能执行monitorexit指令的线程一定是拥有当前对象的monitor的所有权的线程。
2、当执行monitorexit时会将monitor的进入数减1。当monitor的进入数减为0时,当前线程退出monitor,不再拥有monitor的所有权,此时这个monitor阻塞的线程可以尝试去获取这个monitor的所有权。
可见性
synchronized通过内存屏障保证可见性,同样的我们知道volatile是通过内存屏障来保证可见性的,
1、monitorenter指令之后,synchronized内部的共享变量,每次读取数据的时候被强制从主内存读取最新的数据。
2、monitorexit指令也具有Store屏障的作用,也就是让synchronized代码块内的共享变量,如果数据有变更的,强制刷新回主内存。
数据修改之后立即刷新回主内存,其他线程进入synchronized代码块后,使用共享变量的时候强制读取主内存的数据。
有序性
同样的,synchronized也是通过monitorenter、monitorexit指令嵌入上面的内存屏障,既具有加锁、释放锁的功能,同时也具有内存屏障的功能
java中synchronized关键字基础-1的更多相关文章
- java中synchronized关键字分析
今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...
- Java中synchronized关键字理解
好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...
- java中synchronized关键字的用法
在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...
- Java关键字-----------------java中synchronized关键字的用法
在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...
- Java中synchronized关键字你知道多少
1.什么是synchronized 我们将其理解为同步锁,可以实现共享资源的同步访问,解决线程并发的安全问题.synchronize翻译成中文:同步,使同步.synchronized:已同步. 1.1 ...
- Java的synchronized关键字:同步机制总结
JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...
- 从分布式锁角度理解Java的synchronized关键字
分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ...
- 008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字
008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字 关键字 关键字就是一些有特殊意义的词 之前学习的程序中涉及到的关键字 Java中 ...
- 【Java_基础】Java中Native关键字的作用
本篇博文转载与:Java中Native关键字的作用
随机推荐
- 【每日日报】第四十七天---<div>
1 学习HTML HTML <div> 元素是块级元素,它可用于组合其他 HTML 元素的容器. <div> 元素没有特定的含义.除此之外,由于它属于块级元素,浏览器会在其前后 ...
- git总是需要输入用户名密码问题解决
解决办法: git bash进入你的项目目录,输入: git config --global credential.helper store 然后你会在你本地生成一个文本,上边记录你的账号和密码.当然 ...
- linux-RHEL7.0 —— 《Linux就该这么学》阅读笔记
目录 linux-RHEL7.0 安装部署 修改root密码 RPM(红帽软件包管理器) YUM(软件仓库) Systemd初始化进程 总结 linux命令 帮助命令 man 系统工作命令 echo ...
- EMS邮箱数据库常用命令(一)
案例任务:创建名为"book"的邮箱数据库,数据库文件和日志文件存储位置为"c:\book". 键入以下命令. New-MailboxDatabase -Nam ...
- AcWing 1047. 糖果
题目链接 题目描述: 由于在维护世界和平的事务中做出巨大贡献,Dzx被赠予糖果公司2010年5月23日当天无限量糖果免费优惠券. 在这一天,Dzx可以从糖果公司的 N 件产品中任意选择若干件带回家享用 ...
- js知识梳理4.继承的模式探究
写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者.有发现什么问题的,欢迎留言指出 ...
- 创建可以运行宿主机GPU的容器
1.安装NVIDIA Container Runtime apt-get参考https://blog.csdn.net/li_ellin/article/details/107180516 yum参考 ...
- MySQL存储引擎、基础数据类型、约束条件
MySQL存储引擎 存储引擎 # 存储引擎可以堪称是处理数据的不同方式 # 查看存储引擎的方式 show engines; # 需要掌握的四个存储引擎 MyISAM MySQL5.5之前的默认的存储引 ...
- Linux 开启远程访问
系统:Ubuntu16.0 虚拟机 问题:Windows访问Ubun被拒绝 解决方法: 1.先检测是否安装SSH服务 1 sudo apt-get install ssh 2.编辑ssh配置文件 1 ...
- 论文解读(MLGCL)《Multi-Level Graph Contrastive Learning》
论文信息 论文标题:Structural and Semantic Contrastive Learning for Self-supervised Node Representation Learn ...