java中实现线程互斥的关键词_简单的互斥同步方式——synchronized关键字详解

2. synchronized的原理和实现细节

2.1 synchronized可以用在那些地方

静态方法,锁对象为当前类的class对象,不用显式指定

实例方法,锁对象为当前实例对象,不用显式指定

同步代码块,锁对象为括号中指定的对象,必须显式指定

被synchronized修饰的方法或者代码块,同一时刻只能有一个线程能够访问它。

2.2 synchronized是如何实现线程互斥访问的

虽然对于同步方法和同步代码块的底层细节略有不同,但都可以这么理解:对于被synchronized关键字修饰的代码区域,java虚拟机会在开始的位置插入monitorenter指令,而在结束和异常处插入monitorexit指令,每一个monitorenter指令必定有一个monitorexit指令与其配对。线程在执行到monitorenter指令时,将会尝试获取锁对象的monitor(监视器),该线程将进入同步方法或同步代码块中,同时monitor被锁定,防止被多个线程同时获取。获取monitor失败的线程将被阻塞在同步块或同步方法的入口处,整个过程如下图所示。

785a417b7fe6c4b0ae4be485fe0561b8.png

2.3 对象锁的monitor信息存储在哪

正如上面介绍的那样,任何对象都可以作为synchronized代码块的锁,而每个对象锁都有个monitor与之关联,线程通过获取该monitor的所有权来实现对被同步代码的互斥访问。这个monitor信息存储对象的对象头重。

2.4 monitor信息在对象头中的实现细节

对象锁的monitor信息是存储在该对象的对象头中。对象头的基本信息主要包括

01997ca12a78f5524ca0ea0db36dd04a.png

由于锁信息是在Mark Word中,我们继续看看Mark Word到底包括哪些信息

c1aff596a1438104de4a13a173d8a914.png

内容比较多,不用强行记忆,只要知道大概有些东西就行了。

3. synchronized的内存语义

3.1 synchronized的可见性分析

由JMM的happens-before规则可知,对同步锁的释放happens-before于对同步锁的获取,因此在A线程释放锁之前对同步区域内共享变量作的修改,另一个线程B获取锁后将能够马上看到这种变化。它实现的原理和volatile类似

A线程释放锁时,JMM会把该线程对应的工作内存中的共享变量刷新到主存中

B线程获取锁后,JMM会把该线程对应的工作内存中的共享变量置为无效,同步代码块中的共享变量必须从主存中获取。

因此,如果共享变量只在同步代码块或者同步方法中被用到,那它是没必要用volatile修饰的!

3.2 synchronized禁止指令重排吗

那同步代码块会禁止指令重排吗?答案是不会。但只要同步块中的共享变量对其他线程不可见,那么我们就不必担心它引起的副作用。下面就是一个典型的例子

静态内部类的懒汉式实现

public class Singleton {

private Singleton() {

}

static class SingletonHolder {

public static final Singleton INSTANCE = new Singleton();

}

public static Singleton getInstance() {

return SingletonHolder.INSTANCE;

}

}

这是线程安全的实现方式,尽管INSTANCE变量没有用volatile修饰,但我们不用担心指令重排序带来的线程不安全问题。因为

INSTANCE = new Singleton();

是在类初始化的过程中执行的.JVM在Class文件被加载后,被线程使用前会执行类的初始化。这个过程会通过一个初始化锁进行同步(对于每一个类或接口,都有唯一的初始化锁),也就是说只有一个线程能获取该锁并执行这段代码,其他无法线程无法访问到INSTANCE变量,故重排序对其他线程不可见,整个过程是线程安全的。

4.锁的优化

为了减少频繁获得和释放锁的性能开销,JVM做了一系列优化。锁一共分为4种状态,级别从低到高依次为:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态。锁的状态会随着竞争的加剧逐渐升级,获得和释放锁的性能开销也逐渐加大,且锁只能升级而不能降级。为什么需要这么设置,它们各自又有什么特点,什么时候会出发锁的升级?

偏向锁: 当线程第一次访问同步块时,锁为偏向锁,该线程将一直持有偏向锁,直到有其他线程竞争该锁,该线程才释放锁,偏向锁也升级为轻量级锁。持有偏向锁的线程只在第一次获取时会进行CAS同步,接下来的访问和释放锁将不需要进行任何同步操作。

轻量级锁:轻量级锁在获取锁的时候会使用CAS操作将锁对象头的mark word替换到线程的栈帧中,释放锁则使用CAS替换回来。竞争线程不会阻塞,而是使用自旋的方式等待,同时轻量级锁将升级为重量级锁。

重量级锁:获取和释放锁更消耗性能,且竞争锁失败的线程将被阻塞。

下面是锁升级时的状态图

eb0cfc68ee6e29f8d4599f90569e5a87.png

5. 总结

synchronized可以起到独占锁的作用,使多线程互斥的访问被其修饰的代码。虽然这种串行化会极大影响执行速度,但是能很好的保证线程安全,是开发中最经常使用的多线程技术之一。synchronized和volatile一样保证了多线程之间的可见性,又由于线程访问时的独占性对其他线程屏蔽了指令重排的细节,故而可以说是比volatile更重量级也更可靠的同步工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/441714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java类匿名类实例_Java匿名类,匿名内部类实例分析

本文实例讲述了Java匿名类,匿名内部类。分享给大家供大家参考,具体如下:本文内容:内部类匿名类首发日期 :2018-03-25内部类:在一个类中定义另一个类,这样定义的类称为内部类。【包含内部类的类可…

【HDU - 6441】Find Integer (费马大定理 + 奇偶数列法构造勾股定理)

题干: people in USSS love math very much, and there is a famous math problem . give you two integers nn,aa,you are required to find 22 integers bb,cc such that ananbncnbncn. Input one line contains one integer TT;(1≤T≤1000000)(1≤T≤100000…

算法学习 母函数

母函数又称生成函数。定义是给出序列:a0,a1,a2,.......ak,......,那么函数G(x)a0a1*xa2*x2......ak*xk称为序列a0,a1,a2,.......ak,......的母函数(即生成函数)。 例如:序列1,2,3.......n的生成函数为:G(x)x2x23x3........nxn。点此链接:百度百科 特别…

plsq卸载 删除注册表、_win10操作系统下oracle11g客户端/服务端的下载安装配置卸载总结...

win10操作系统下oracle11g客户端/服务端的下载安装配置卸载总结一:前提注意:现在有两种安装的方式1. oracle11g服务端(64位)oracle客户端(32位)plsql(32位)2. oracle11g服务端(32位)plsql(32位)这里我选择的是第二种 原因是 :首先需要明确ora…

【HDU -1568】 Fibonacci(斐波那契通项公式+取对数)

Fibonacci Problem Description 2007年到来了。经过2006年一年的修炼,数学神童zouyu终于把0到100000000的Fibonacci数列 (f[0]0,f[1]1;f[i] f[i-1]f[i-2](i>2))的值全部给背了下来。 接下来,CodeStar决定要考考他,于是每问他一个数字&a…

php多线程模拟请求,浅谈php使用curl模拟多线程发送请求

每个PHP文件的执行是单线程的,但是php本身也可以用一些别的技术实现多线程并发比如用php-fpm进程,这里用curl模拟多线程发送请求。php的curl多线程是通过不断调用curl_multi_exec来获取内容,这里举一个demo来模拟一次curl多线程并发操作。//设…

php hbase thrift,PHP使用Thrift操作Hbase

系统架构图HBase 启动 Thrift服务hbase启动thrift服务// 进入安装的hbase bin目录下// 执行hbase-daemon.sh start thrift2需要注意的是,这里启动的是thrift2服务,如果需要启动thrift服务只需要将thrift2改为thrift就可以了,具体thrift和thri…

【CodeForces - 761D 】Dasha and Very Difficult Problem (构造,思维)

题干: Dasha logged into the system and began to solve problems. One of them is as follows: Given two sequences a and b of length n each you need to write a sequence c of length n, the i-th element of which is calculated as follows: ci  bi -…

【CodeForces - 761B】Dasha and friends (思维,模拟,构造)

题干: Running with barriers on the circle track is very popular in the country where Dasha lives, so no wonder that on her way to classes she saw the following situation: The track is the circle with length L, in distinct points of which there…

php字符串变量,PHP 字符串变量

PHP 字符串变量字符串变量用于存储并处理文本。PHP 中的字符串变量字符串变量用于包含有字符的值。在创建字符串之后,我们就可以对它进行操作了。您可以直接在函数中使用字符串,或者把它存储在变量中。在下面的实例中,我们创建一个名为 txt 的…

【CodeForces - 761C】Dasha and Password (暴力可过,标解dp,字符串,有坑总结)

题干: After overcoming the stairs Dasha came to classes. She needed to write a password to begin her classes. The password is a string of length n which satisfies the following requirements: There is at least one digit in the string,There is a…

php4和php5的区别,什么是PHP 4和PHP 5之间的区别是什么-php是什么文件

?尽管PHP 5是故意设计成兼容尽可能与以前的版本,也有一些显著的变化。 其中的一些变化包括: 一个新的OOP模型基础上,Zend引擎2.0 改进MySQL支持的一个新推广 内置SQLite的原生支持 一个新的错误报告不断, E_STRICT &am…

ecshop php升级,升级-安装与升级- ECShop帮助

ECShop V2.6.2版本有GBK和UFT-8两种编码格式的程序,而低于ECShop V2.6.0 的版本只有UTF-8 编码的(这些版本包括 ECShop 2.5.1、ECShop 2.5.0、ECShop 2.1.5、ECShop 2.1.2b等), 这些版本升级到ECShop V2.6.2均可以使用本程序升级。相同版本的升级只需要覆…

php页面转发,php如何实现页面路由转发

php实现页面路由转发的方法:首先配置nginx服务器,在【.htaccess】中写上nginx的语法;然后打开根目录的【index.php】,编写文件路由即可。php实现页面路由转发的方法:1、配置nginx服务器nginx服务器不会自动读取.htacce…

【CodeForces - 764D】Timofey and rectangles (四色定理 + 找规律 + 构造)

题干: One of Timofeys birthday presents is a colourbook in a shape of an infinite plane. On the plane n rectangles with sides parallel to coordinate axes are situated. All sides of the rectangles have odd length. Rectangles cannot intersect, bu…

mysql innodb 全表锁,Mysql InnoDB行锁及表锁分享

一. 背景知识二. 步入正题:表锁和行锁1.1. 表锁 vs 行锁在 MySQL 中锁的种类有很多,但是最基本的还是表锁和行锁:表锁指的是对一整张表加锁,一般是 DDL 处理时使用,也可以自己在 SQL 中指定;而行锁指的是锁…

php万能查询用预,PHP 与 mysql

一、php 的 sql 注入攻击1.1、什么是 sql 注入攻击用户提交一段数据库查询代码,根据返回的结果,获得某些他想得到的数据。比如 :查询某个管理员是否存在,一般程序员会这么写$sql "select * from user where nameluluyii and…

php 判断radio选中哪个,jquery如何判断单选按钮radio是否选中

jquery判断单选按钮radio是否选中的方法:1、加载页面的时候获取id,代码为【var fs$("#"id).val()】;2、点击按钮的时候获取id,代码为【var id $(this).attr("id")】。本教程操作环境:windows7系统…

matlab在光学实验中的应用,matlab在光学实验中的应用

matlab在光学实验中的应用 《MATLAB》课程论文MATLAB 在光学实验中的应用姓名:学号:专业:班级:指导老师:学院:完成日期:1MATLAB 在波动光学中的应用(姓名:郑苗苗 12012241736 2012 级…

【CF#192 A】Funky Numbers (二分,查找,二元组)

题干: As you very well know, this years funkiest numbers are so called triangular numbers (that is, integers that are representable as , where k is some positive integer), and the coolest numbers are those that are representable as a sum of two…