Synchronized 失效原因
Synchronized 同步出现失效
Synchronized ,大家都知道这个是Java 提供的一种原子性内置锁,其实现原理是通过获取对象的监视器monitor进行来实现同步的,只有当线程获取到对象monitor才能继续执行,否则该线程进行阻塞(等待)。
示例:
public class DemoServiceImpl {
@Autowired
private DemoDao demoDao;
// 根据id获取序列号,获取完之后进行 + 1
@Transactional
public synchronized String getSn(Long id) {
DemoSn sn = demoDao.getSnById(id);
sn.setSn(sn.getSn() + 1);
demoDao.update(sn);
return sn.getSn().toString();
}
}
描述一下代码示例: 该方法涉及++ 1 ,当如果多个线程进行调用该方法时,会出现数据安全性问题,所以我在这里进行加了 Synchronized, 保证该方法的每次执行只能允许一个线程进来。
本以为这里加了 Synchronized, 就是线程安全了,但是经过测试之后发现,这里同步锁并没有起作用,多个线程进行调用该方法时,还是出现返回的 值重复。
Synchronized 失效原因:
先简单介绍一下Spring @Transactional执行原理: @Transactional 注解是Spring 提供来进行控制事务的注解,当注解标明在方法上时, 则会对 该方法进行做AOP 增强(动态代理),然后在方法执行前,开启事务,执行后提交事务。
如果上述示例方法只添加了 Synchronized, 并没有标明@Transactional, 因为加了同步锁,所以getSn() 一次只能允许一个线程进入, 执行过程:
A(线程): DemoServiceImpl#getSn() > B(线程): DemoServiceImpl#getSn()
如果上述示例方法添加了 Synchronized,并标明@Transactional 线程的执行过程:
A(线程): Spring begins transactional > DemoServiceImpl#getSn() > Spring commits transactional
B(线程): Spring begins transactional > DemoServiceImpl#getSn() > Spring commits transactional
这里看着是没有问题
开启事务 -> 执行方法体 -> 提交事务
但是这里也恰恰是出现Synchronized 失效的关键
Synchronized 失效关键原因:是因为Synchronized锁定的是当前调用方法对象,而Spring AOP 处理事务会进行生成一个代理对象,并在代理对象执行方法前的事务开启,方法执行完的事务提交,所以说,事务的开启和提交并不是在 Synchronized 锁定的范围内。出现同步锁失效的原因是:当A(线程) 执行完getSn()方法,会进行释放同步锁,去做提交事务,但在A(线程)还没有提交完事务之前,B(线程)进行执行getSn() 方法,执行完毕之后和A(线程)一起提交事务, 这时候就会出现线程安全问题。
作者:技术基地
链接:https://www.jianshu.com/p/3e30cc705f09
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Synchronized 失效原因的更多相关文章
- oracle 索引失效原因及解决方法
oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...
- 清除浮动元素的margin-top失效原因(更改之前的错误)
//样式代码body,div{ margin:; padding:; } .box1{ background:#900; width:200px; height:200px; margin:20px ...
- 高阶篇:4.2.2)DFMEA层级分明的失效模式、失效后果、失效原因
本章目的:明确失效模式.失效后果.失效原因的定义,分清楚层次关系,完成DFMEA这部分的填写. 1.失效模式,失效后果,失效原因的定义: 这是FEMEA手册第四册中的定义. 1.1 潜在失效模式 (b ...
- kubectl get 后按2次tab键命令补全的失效原因分析
kubectl get 后按2次tab键命令补全的失效原因分析 2019/10/28 Chenxin a.bash客户端工具 在centos用户下, cd ~;echo "source &l ...
- z-index失效原因分析——由一个bug引发的对层叠上下文和z-index属性的深度思考
新年刚开工就被一个bug虐得整个人都不好了,特地记录下. (一)bug描述 在一个fixed-data-table(一个React组件)制作的表格中,需要给表头的字段提示的特效,所以做了一个提示层,但 ...
- 【转】Android中removeCallbacks失效原因
原文网址:http://blog.sina.com.cn/s/blog_6714fba70100wtx1.html 在Android开发中会使用Handle的removeCallbacks函数,该函数 ...
- Oracle索引失效原因及解决方法
一.Oracle索引失效的原因 1使用否定关键字 !=, <> ,not in,not exist select * fromdrama where id <> 1,Mysql ...
- spring管理hibernate,mybatis,一级缓存失效原因
mybatis缓存:一级缓存和二级缓存 hibernate缓存:一级缓存和二级缓存 关于缓存: 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器, 其作用是为了减少应 ...
- Session 失效原因
转载http://blog.csdn.net/LLorJJ999/article/details/4107464 昨天去GTSC面试,有面试官问我关于Session丢失之后怎么查的问题,说老实话,开发 ...
随机推荐
- LinkedList简介
原文:https://blog.csdn.net/GongchuangSu/article/details/51527042 LinkedList简介 LinkedList 是一个继承于Abstrac ...
- 远程连接elasticsearch遇到的问题
本文转自:https://blog.csdn.net/xuchuangqi/article/details/78989940 1.首先要远程连接就要把配置文件的network.host: 改为 net ...
- conftest.py作用范围
前言 一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用.在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录 ...
- vue v-for直接循环数字
<svg class="icon" aria-hidden="true" v-for="index of 5" :key=" ...
- 使用Python创建AI比你想象的轻松
使用 Python 创建 AI 比你想象的轻松 可能对AI领域,主要开发阶段,成就,结果和产品使用感兴趣.有数百个免费源和教程描述使用Python的AI.但是,没有必要浪费你的时间看他们.这里是一个详 ...
- 自动部署脚本-bash
from here !/bin/bash Check if user is root if [ $(id -u) != "0" ]; then Echo_Red "Err ...
- 基于LVM(逻辑卷管理)的快照原理
一.为甚么不管多大的逻辑卷进行备份,快照都会在几秒之内完成? 快照在拍摄的一瞬间,系统会记录那个时间点逻辑卷的状态.数据等,此时拍下的快照相当于一张白纸.如图所示 快照做好后,随着时间的推移,源卷里的 ...
- 【转】应用宝基于Robotium自动化测试
(转载:http://tmq.qq.com/2016/05/robotium_for_app_test/) 1 背景目的应用宝项目组采用FT(Feature Team)模式,整个项目组分为多个FT,而 ...
- form 校验
import refrom django.forms import Formfrom django.forms import widgetsfrom django.forms import field ...
- node项目自动化部署--基于Jenkins,Docker,Github(2)配置节点
上一篇文章中准备工作已经完成的差不多了 这一篇主要讲解 Jenkins 上面的相关配置 为了让代码部署到所有的子节点上 所以我们首先需要在 Jenkins 中添加我们希望代码部署到的节点 配置节点 首 ...