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的更多相关文章

  1. java中synchronized关键字分析

    今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...

  2. Java中synchronized关键字理解

    好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式 ...

  3. java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  4. Java关键字-----------------java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  5. Java中synchronized关键字你知道多少

    1.什么是synchronized 我们将其理解为同步锁,可以实现共享资源的同步访问,解决线程并发的安全问题.synchronize翻译成中文:同步,使同步.synchronized:已同步. 1.1 ...

  6. Java的synchronized关键字:同步机制总结

    JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...

  7. 从分布式锁角度理解Java的synchronized关键字

    分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ...

  8. 008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字

    008 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 02 Java 中的关键字 关键字 关键字就是一些有特殊意义的词 之前学习的程序中涉及到的关键字 Java中 ...

  9. 【Java_基础】Java中Native关键字的作用

    本篇博文转载与:Java中Native关键字的作用

随机推荐

  1. android.content.res.Resources$NotFoundException: String resource ID #0x0报错

    报错:android.content.res.Resources$NotFoundException: String resource ID #0x0 原因:在setText()中使用了int型的参数 ...

  2. 界面跳转+Android Studio Button事件的三种方式

    今天学习界面跳转 java类总是不能新建成功 看了网上教程 (20条消息) 关于android studio无法创建类或者接口问题的解决方法_qq_39916160的博客-CSDN博客 可以新建了 但 ...

  3. Java中JSONArray转换成int[]的办法

    今天写项目的时候要做一个MyBatis的带IN子句的删除,于是用一个整型数组来保存待删除数据的ID 从前端将JSON字符串搞过来之后如何将JSONArray转换成int类型数组就成了个问题 下面是我的 ...

  4. git clone 遇到的问题

    经常遇到这个问题, 所以今天决定把它记录下来 当使用git clone时,会报Please make sure you have the correct access rights and the r ...

  5. Jenkins 脚本命令行应用总结

    Jenkins脚本命令行应用总结 测试环境 Jenkins 2.304 脚本命令行入口 Jenkins主页→系统管理→脚本命令行 遍历项目 例子:获取所有自由风格项目及相关项目信息 def proje ...

  6. IDEA-2020版本 Gradle项目控制台输出乱码

    点击Help->Edit custom vm options 加入下面这一行 -Dfile.encoding=utf-8 最后当然要重启idea了

  7. ICMP TYPE CODE 对应表

    下载ping程序源代码等信息,可以在这里下载 [root@ht8 network-scripts]# ping -V ping utility, iputils-s20160308 //ping实用程 ...

  8. Python 图_系列之纵横对比 Bellman-Ford 和 Dijkstra 最短路径算法

    1. 前言 因无向.无加权图的任意顶点之间的最短路径由顶点之间的边数决定,可以直接使用原始定义的广度优先搜索算法查找. 但是,无论是有向.还是无向,只要是加权图,最短路径长度的定义是:起点到终点之间所 ...

  9. typescript使用入门及react+ts实战

    ts介绍 TypeScript是一种由微软开发的自由和开源的编程语言.它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程. 与js关系 ts与js区 ...

  10. Python BeautifulSoup4 爬虫基础、多线程学习

    针对 崔庆才老师 的 https://ssr1.scrape.center 的爬虫基础练习.Threading多线程库.Time库.json库.BeautifulSoup4 爬虫库.py基本语法