巨人大哥谈Java中的Synchronized关键字用法
巨人大哥谈Java中的Synchronized关键字用法
认识synchronized
对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方价格synchronized基本上就搞定 了,如果说不考虑性能问题的话,这一操绝对能应对百分之九十以上的情况,若对于性能方面有要求的话就需要额外的知识比如读写锁等等。本文目的先了解透彻synchronized的基本原理。
Synchronized的基本使用
Synchronized的作用主要有三个:
(1)确保线程互斥的访问同步代码
(2)保证共享变量的修改能够及时可见
(3)有效解决重排序问题。
从语法上讲,Synchronized总共有三种用法:
(1)修饰普通方法
(2)修饰静态方法
(3)修饰代码块
package com.paddx.test.concurrent;
public class SynchronizedDemo {
public void method() {
synchronized (this) {
System.out.println("Method 1 start");
}
}
}
对于上述方法我们很容易就知道是线程安全的,具体是怎么做的到的线程安全呢,对class通过javap编译结果如下:
monitorenter
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1、如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2、如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
monitorexit
执行monitorexit的线程必须是objectref所对应的monitor的所有者。
指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。
通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。
原理总结
每个对象都有一个内部的锁或者叫做是监视器,称之为monitor,当一个方法加上synchronized关键字的时候,如果一个线程想执行这个方法那么首先需要获取这个对象的monirot权限,对应到指令上面也就是需要获取monitorenter 指令,如果一个对象获取到这个指令之后,那么monitor的进入数为1,当其他线程再次获取的时候发现这个对象的monitor对象被别的线程所占用,那么进入阻塞状态,知道占用这个对象的线程执行monitorexit,设置进入数为0为止。
如果synchronized加在普通方法上,那么有效的范围是多个线程执行同一个对象的方法。通过上面的解释应该比较容易理解了,因为不同的对象获取的是不同的monitor监视器,自然也就不存在占用–等待的过程了。如果是加载static方法上那么需要获取的就是这个对象所在class的Class对象,所以此时不管是几个对象,对应的都是同一个class对象,也就是说多个线程又存在对同一个monitor的占用—等待的过程了。所以说加载static上是对于整个类文件有效。
巨人大哥谈Java中的Synchronized关键字用法的更多相关文章
- Java中的Synchronized关键字用法
认识synchronized 对于写多线程程序的人来说,经常碰到的就是并发问题,对于容易出现并发问题的地方加上synchronized修饰符基本上就搞定 了,如果说不考虑性能问题的话,这一招绝对能应对 ...
- 浅谈Java中的final关键字
浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- 深入理解java中的synchronized关键字
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...
- “无法改变的设计”——浅谈Java中的final关键字
在Java中,final关键字可以用来修饰类.变量(包括成员变量和局部变量).方法,下面从这三个方面分别说明. final方法 当一个方法被final修饰时,表明这个方法不能被子类重写. 下面程序试图 ...
- java中的synchronized关键字
参考:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 多线程并发问题的根因: 在一个对象中有一个变量i=0,有两个线 ...
- Java中使用同步关键字synchronized需要注意的问题
在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.synchronized既可以加在一段代码上,也可以加在 ...
- 巨人大哥谈Web应用中的Session(session详解)
巨人大哥谈Web应用中的Session(session详解) 虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术. ...
- 对kotlin和java中的synchronized的浅谈
synchronized在java中是一个关键字,但是在kotlin中是一个内联函数.假如分别在java和kotlin代码锁住同一个对象,会发生什么呢,今天写了代码试了试.首先定义people类 12 ...
- 浅谈Java中的关键字
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...
随机推荐
- Initialization error SQL*Net not properly installed
1.错误描述 2.错误原因 由于我在64位操作系统上安装了32位PL/SQL导致出错,出现兼容性连接问题 3.解决办法 安装一个32位的Oracle客户端,Tools-Preferences-Orac ...
- Docker 小记 — Compose & Swarm
前言 任何相对完整的应用服务都不可能是由单一的程序来完成支持,计划使用 Docker 来部署的服务更是如此.大型服务需要进行拆分,形成微服务集群方能增强其稳定性和可维护性.本篇随笔将对 Docker ...
- TCP粘包、拆包及解决
TCP属于传输层的协议,传输层除了有TCP协议外还有UDP协议.那么UDP是否会发生粘包或拆包的现象呢?答案是不会.UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示 ...
- 由内搜推送思考Kafka 的原理
刚入公司的两周多,对CDX项目有了进一步的认识和理解,在这基础上,也开始了解部门内部甚至公司提供的一些中间服务.CDX项目中涉及到的二方服务和三方服务很多,从之前写过的SSO,Auth,到三方图库的各 ...
- APIO2010特别行动队
斜率优化 # include <stdio.h> # include <stdlib.h> # include <iostream> # include <s ...
- 论文笔记(1):From Image-level to Pixel-level Labeling with Convolutional Networks
文章采用了多实例学习(MIL)机制构建图像标签同像素语义的关联 . 该方法的训练样本包含了70 万张来自ImageNet的图片,但其语义分割的性能很大程度上依赖于复杂的后处理过程,主要包括图像级语义的 ...
- weblogic的使用
1.怎么修改weblogic的端口 创建好域之后,去域的下面找到config.xml文件,在里面加上<listen-port>80</listen-port>即可,访问时不用加 ...
- Treesoft数据库管理系统使用说明
数据列表页面有以下功能:1.直接新添数据行2.直接双击编辑数据3.勾选复制新增数据4.数据按字段排序5.数据列过滤6.结果结果集过滤7.导出数据等 表结构设计页面有以下功能:1.直接新增.删除字段2. ...
- 32.Django form组件
Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 创建Form类时,主要涉及到 [ ...
- JAVA面向对象思想
1.面向对象的基本特征 面向对象具有三个基本特征:封装.多态.继承. 1)封装 封装指的是将对象的实现细节隐藏起来,然后通过一些公用方法来暴露该对象的功能. ...