java并发中的Synchronized关键词
文章目录
- 为什么要同步
- Synchronized关键词
- Synchronized Instance Methods
- Synchronized Static Methods
- Synchronized Blocks
java并发中的Synchronized关键词
如果在多线程的环境中,我们经常会遇到资源竞争的情况,比如多个线程要去同时修改同一个共享变量,这时候,就需要对资源的访问方法进行一定的处理,保证同一时间只有一个线程访问。
java提供了synchronized关键字,方便我们实现上述操作。
为什么要同步
我们举个例子,我们创建一个类,提供了一个setSum的方法:
public class SynchronizedMethods {private int sum = 0;public void calculate() {setSum(getSum() + 1);}
}
如果我们在多线程的环境中调用这个calculate方法:
@Testpublic void givenMultiThread_whenNonSyncMethod() throws InterruptedException {ExecutorService service = Executors.newFixedThreadPool(3);SynchronizedMethods summation = new SynchronizedMethods();IntStream.range(0, 1000).forEach(count -> service.submit(summation::calculate));service.shutdown();service.awaitTermination(1000, TimeUnit.MILLISECONDS);assertEquals(1000, summation.getSum());}
按照上面的方法,我们预计要返回1000, 但是实际上基本不可能得到1000这个值,因为在多线程环境中,对同一个资源进行同时操作带来的不利影响。
那我们怎么才能够建线程安全的环境呢?
Synchronized关键词
java提供了多种线程安全的方法,本文主要讲解Synchronized关键词,Synchronized关键词可以有很多种形式:
- Instance methods
- Static methods
- Code blocks
当我们使用synchronized时,java会在相应的对象上加锁,从而在同一个对象等待锁的方法都必须顺序执行,从而保证了线程的安全。
Synchronized Instance Methods
Synchronized关键词可以放在实例方法的前面:
public synchronized void synchronisedCalculate() {setSum(getSum() + 1);}
看下调用结果:
@Test
public void givenMultiThread_whenMethodSync() {ExecutorService service = Executors.newFixedThreadPool(3);SynchronizedMethods method = new SynchronizedMethods();IntStream.range(0, 1000).forEach(count -> service.submit(method::synchronisedCalculate));service.awaitTermination(1000, TimeUnit.MILLISECONDS);assertEquals(1000, method.getSum());
}
这里synchronized将会锁住该方法的实例对象,多个线程中只有获得该实例对象锁的线程才能够执行。
Synchronized Static Methods
Synchronized关键词也可以用在static方法前面:
public static synchronized void syncStaticCalculate() {staticSum = staticSum + 1;}
Synchronized放在static方法前面和实例方法前面锁住的对象不同。放在static方法前面锁住的对象是这个Class本身,因为一个Class在JVM中只会存在一个,所以不管有多少该Class的实例,在同一时刻只会有一个线程可以执行该放方法。
@Testpublic void givenMultiThread_whenStaticSyncMethod() throws InterruptedException {ExecutorService service = Executors.newCachedThreadPool();IntStream.range(0, 1000).forEach(count ->service.submit(SynchronizedMethods::syncStaticCalculate));service.shutdown();service.awaitTermination(100, TimeUnit.MILLISECONDS);assertEquals(1000, SynchronizedMethods.staticSum);}
Synchronized Blocks
有时候,我们可能不需要Synchronize整个方法,而是同步其中的一部分,这时候,我们可以使用Synchronized Blocks:
public void performSynchronizedTask() {synchronized (this) {setSum(getSum() + 1);}}
我们看下怎么测试:
@Testpublic void givenMultiThread_whenBlockSync() throws InterruptedException {ExecutorService service = Executors.newFixedThreadPool(3);SynchronizedMethods synchronizedBlocks = new SynchronizedMethods();IntStream.range(0, 1000).forEach(count ->service.submit(synchronizedBlocks::performSynchronizedTask));service.shutdown();service.awaitTermination(100, TimeUnit.MILLISECONDS);assertEquals(1000, synchronizedBlocks.getSum());}
上面我们同步的是实例,如果在静态方法中,我们也可以同步class:
public static void performStaticSyncTask(){synchronized (SynchronizedMethods.class) {staticSum = staticSum + 1;}}
我们看下怎么测试:
@Testpublic void givenMultiThread_whenStaticSyncBlock() throws InterruptedException {ExecutorService service = Executors.newCachedThreadPool();IntStream.range(0, 1000).forEach(count ->service.submit(SynchronizedMethods::performStaticSyncTask));service.shutdown();service.awaitTermination(100, TimeUnit.MILLISECONDS);assertEquals(1000, SynchronizedMethods.staticSum);}
本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/Synchronized
更多精彩内容且看:
- 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
- Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
更多内存可以参考http://www.flydean.com/java-concurrent-synchronized/
java并发中的Synchronized关键词相关推荐
- java并发中CountDownLatch的使用
文章目录 主线程等待子线程全都结束之后再开始运行 等待所有线程都准备好再一起执行 停止CountdownLatch的await java并发中CountDownLatch的使用 在java并发中,控制 ...
- java并发中ExecutorService的使用
文章目录 创建ExecutorService 为ExecutorService分配Tasks 关闭ExecutorService Future ScheduledExecutorService Exe ...
- HashMap在java并发中如何发生死循环
转载自 HashMap在java并发中如何发生死循环 在多线程环境中,使用HashMap进行put操作时会引起死循环,导致CPU使用接近100%,下面通过代码分析一下为什么会发生死循环. 首先先分 ...
- 【死磕Java并发】—–深入分析synchronized的实现原理
记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予它一个名字"同步", ...
- Java线程中关于Synchronized的用法
synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代 ...
- Java并发编程之synchronized关键字解析
前言 公司加班太狠了,都没啥时间充电,这周终于结束了.这次整理了Java并发编程里面的synchronized关键字,又称为隐式锁,与JUC包中的Lock显示锁相对应:这个关键字从Java诞生开始就有 ...
- Java 并发编程:Synchronized 及其实现原理
作者:liuxiaopeng 原文链接: www.cnblogs.com/paddix/p/5367116.html 一.Synchronized的基本使用 Synchronized是Java中解决并 ...
- 死磕Java并发:深入分析synchronized的实现原理
本文转载自公众号: Java技术驿站 记得刚刚开始学习Java的时候,一遇到多线程情况就是synchronized.对于当时的我们来说,synchronized是如此的神奇且强大.我们赋予它一个名字& ...
- 并发中的Synchronized、Lock、Volite、Map、ThreadLocal
文章目录 Synchronized synchronized 的三种应用方式 synchronized 括号后面的对象 synchronized 的锁的原理 Java 对象头 synchronized ...
最新文章
- 在闲鱼传疯了,某大厂P8面试题库泄漏!
- 使用AppCompat项目模版
- Nodejs开源项目推荐
- vim 树形目录插件NERDTree安装及简单用法
- 关于mpvue音乐小程序github仓库设置私有的声明
- 原动力CMS PHP域名授权系统V3.0
- Kafka配置文件及解释
- uni-app 实现手写签名
- springboot中使用@Transactional注解事物不生效的原因
- 用matlab做谱分析程序,经典功率谱分析Matlab程序
- 指针详讲(一阶指针和二阶指针等指针各种用法详解)
- Cadence Allegro PCB绘制:布线后的操作教程
- 做产品和运营必须深参这5大人性弱点
- 【Linux 网络】IP校验和计算相关
- 几种常见的Shell:sh、bash、csh、tcsh、ash
- 成功的反义词不是失败,而是什么都不做
- 科普一下什么是企业邮箱,企业邮箱适合场景?
- 基于bitshares的身份认证系统设计思路
- 把Google图书嵌入到网站中
- 开关电源和LDO纹波
热门文章
- 数据分析与挖掘实战-家用电器用户行为分析与事件识别
- python绘图设置标题出现乱码_解决python2 绘图title,xlabel,ylabel出现中文乱码的问题...
- 【Boost】boost库中thread多线程详解4——谈谈recursive_mutex
- socket中的nagle算法
- Sql Server事务日志
- STL 之swap, iter_swap, swap_ranges
- C++的精髓——虚函数
- QUIC/HTTP2相关资料整理
- 数据结构与算法 | 插值查找
- 音视频技术开发周刊 | 183