并发之synchronized关键字的应用
并发之synchronized关键字的应用
synchronized关键字理论基础
前两章我们学习了下java内存模型的相关知识, 现在我们来讲讲逢并发必出现的synchronized关键字。
作用
synchronized是Java中的关键字,是一种同步锁。依赖JVM实现。
JMM对synchronized约束
线程解锁前,必须将变量的最新值刷新回主内存。
线程加锁时,将情况工作内存中变量的共享值,从而使变量从主内存中读取最新的值。
注意:加锁和解锁的锁必须是同一把锁。
synchronized关键字应用方向
它修饰的对象有以下几种:
1.修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2.修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3.修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4.修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
并发测试常用类:
线程池创建方式:
ExecutorService 线程池,每一个线程代表一次并发。
ExecutorService executorService =Executors.newCachedThreadPool();
模拟并发次数:
Semaphore 同一时间可以一同运行的线程数量。
Semaphore semaphore = new Semaphore(threadTotal);
模拟并发总量:
CountDownLatch 运行多少个线程后才能再次往下执行、
CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
实际应用
修饰代码块
/**
* 同步代码块
*/
@Slf4j
public class SyncCodeBlock {
private static final int COUNT = 5;
public void syncCodeBlock(String block) {
synchronized (this){
for(int i =0;i<COUNT;i++){
log.info("同步块{}并发-{}",block,i);
}
}
for(int i =0;i<COUNT;i++){
log.info("异步块{}并发-{}",block,i);
}
}
public void asynCodeBlock(int block) {
for(int i =0;i<COUNT;i++){
log.info("代码块{}并发-{}",block,i);
}
}
public static void main(String[] args) {
ExecutorService executorService =Executors.newCachedThreadPool();
SyncCodeBlock syncCodeBlock = new SyncCodeBlock();
executorService.execute(()->{
syncCodeBlock.syncCodeBlock("A");
});
executorService.execute(()->{
syncCodeBlock.syncCodeBlock("B");
});
}
}
结果
同步块A并发0
同步块A并发1
同步块A并发2
同步块A并发3
同步块A并发4
异步块A并发0
异步块A并发1
异步块A并发2
异步块A并发3
同步块B并发0
同步块B并发1
同步块B并发2
同步块B并发3
同步块B并发4
异步块B并发0
异步块B并发1
异步块A并发4
异步块B并发2
异步块B并发3
异步块B并发4
A线程执行同步代码块时并没有B线程干扰,说明A线程锁住了对象。
A线程执行完同步之后释放了锁,B的同步异步代码块和A的异步代码块才开始执行。
由上述例子可以证明
同步代码块作用范围只在synchronized{}括起来的部分。而锁定锁定的是这个对象本身。
**
@Slf4j
public class SyncMethod {
private static final int COUNT = 5;
public synchronized void syncMethod(String block) {
for(int i =0;i<COUNT;i++){
// log.info("同步{}并发-{}",block,i);
System.out.println("同步"+block+"并发"+i);
}
}
public void asynMethod(String block) {
for(int i =0;i<COUNT;i++){
// log.info("异步块{}并发-{}",block,i);
System.out.println("异步"+block+"并发"+i);
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
SyncMethod syncMethod = new SyncMethod();
executorService.execute(()->{
syncMethod.syncMethod("A");
});
executorService.execute(()->{
syncMethod.syncMethod("B");
});
}
}
作用于方法
同步A并发0
同步A并发1
同步A并发2
同步A并发3
同步A并发4
同步B并发0
同步B并发1
同步B并发2
同步B并发3
同步B并发4
A线程执行同步代码是连续的,并没有B参入。说明锁住了对象
A线程执行完成后B线程执行自己的锁定方法。
上述例子说明作:
同步的作用范围是整个方法而锁定的是整个方法所在对象那个的本身
作用于静态方法、类
public class SyncStaticMethod {
private static final int COUNT = 10;
public synchronized static void syncStaticMethod(String block){
for(int i =0;i<COUNT;i++){
System.out.println("静态同步"+block+"并发"+i);
}
}
public static void asynStaticMethod(String block){
for(int i =0;i<COUNT;i++){
System.out.println("静态异步"+block+"并发"+i);
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for(int j= 0;j<10;j++){
int finalJ = j;
executorService.execute(() -> {
SyncStaticMethod.syncStaticMethod(""+ finalJ);
});
}
}
}
添加关键字效果
静态同步0并发0
静态同步0并发1
静态同步0并发2
静态同步0并发3
静态同步0并发4
静态同步0并发5
静态同步0并发6
静态同步0并发7
静态同步0并发8
静态同步0并发9
静态同步2并发0
静态同步2并发1
静态同步2并发2
静态同步2并发3
静态同步2并发4
静态同步2并发5
静态同步2并发6
静态同步2并发7
静态同步2并发8
静态同步2并发9
静态同步1并发0
静态同步1并发1
静态同步1并发2
静态同步1并发3
静态同步1并发4
静态同步1并发5
静态同步1并发6
静态同步1并发7
静态同步1并发8
静态同步1并发9
静态同步3并发0
静态同步3并发1
静态同步3并发2
静态同步3并发3
静态同步3并发4
静态同步3并发5
静态同步3并发6
静态同步3并发7
静态同步3并发8
静态同步3并发9
静态同步6并发0
静态同步6并发1
静态同步6并发2
静态同步6并发3
静态同步6并发4
静态同步6并发5
静态同步6并发6
静态同步6并发7
静态同步6并发8
静态同步6并发9
静态同步5并发0
静态同步5并发1
静态同步5并发2
静态同步5并发3
静态同步5并发4
静态同步5并发5
静态同步5并发6
静态同步5并发7
静态同步5并发8
静态同步5并发9
静态同步4并发0
静态同步4并发1
静态同步4并发2
静态同步4并发3
静态同步4并发4
静态同步4并发5
静态同步4并发6
静态同步4并发7
静态同步4并发8
静态同步4并发9
静态同步9并发0
静态同步9并发1
静态同步9并发2
静态同步9并发3
静态同步9并发4
静态同步9并发5
静态同步9并发6
静态同步9并发7
静态同步9并发8
静态同步9并发9
静态同步8并发0
静态同步8并发1
静态同步8并发2
静态同步8并发3
静态同步8并发4
静态同步8并发5
静态同步8并发6
静态同步8并发7
静态同步8并发8
静态同步8并发9
静态同步7并发0
静态同步7并发1
静态同步7并发2
静态同步7并发3
静态同步7并发4
静态同步7并发5
静态同步7并发6
静态同步7并发7
静态同步7并发8
静态同步7并发9
静态同步0并发0
静态同步0并发1
静态同步0并发2
静态同步0并发3
静态同步0并发4
静态同步0并发5
静态同步0并发6
静态同步0并发7
静态同步0并发8
静态同步0并发9
静态同步2并发0
静态同步2并发1
静态同步2并发2
静态同步2并发3
静态同步2并发4
静态同步2并发5
静态同步2并发6
静态同步2并发7
静态同步2并发8
静态同步2并发9
静态同步1并发0
静态同步1并发1
静态同步1并发2
静态同步1并发3
静态同步1并发4
静态同步1并发5
静态同步1并发6
静态同步1并发7
静态同步1并发8
静态同步1并发9
静态同步3并发0
静态同步3并发1
静态同步3并发2
静态同步3并发3
静态同步3并发4
静态同步3并发5
静态同步3并发6
静态同步3并发7
静态同步3并发8
静态同步3并发9
静态同步6并发0
静态同步6并发1
静态同步6并发2
静态同步6并发3
静态同步6并发4
静态同步6并发5
静态同步6并发6
静态同步6并发7
静态同步6并发8
静态同步6并发9
静态同步5并发0
静态同步5并发1
静态同步5并发2
静态同步5并发3
静态同步5并发4
静态同步5并发5
静态同步5并发6
静态同步5并发7
静态同步5并发8
静态同步5并发9
静态同步4并发0
静态同步4并发1
静态同步4并发2
静态同步4并发3
静态同步4并发4
静态同步4并发5
静态同步4并发6
静态同步4并发7
静态同步4并发8
静态同步4并发9
静态同步9并发0
静态同步9并发1
静态同步9并发2
静态同步9并发3
静态同步9并发4
静态同步9并发5
静态同步9并发6
静态同步9并发7
静态同步9并发8
静态同步9并发9
静态同步8并发0
静态同步8并发1
静态同步8并发2
静态同步8并发3
静态同步8并发4
静态同步8并发5
静态同步8并发6
静态同步8并发7
静态同步8并发8
静态同步8并发9
静态同步7并发0
静态同步7并发1
静态同步7并发2
静态同步7并发3
静态同步7并发4
静态同步7并发5
静态同步7并发6
静态同步7并发7
静态同步7并发8
静态同步7并发9
public class SyncStaticMethod {
private static final int COUNT = 10;
public synchronized static void syncStaticMethod(String block){
for(int i =0;i<COUNT;i++){
System.out.println("静态同步"+block+"并发"+i);
}
}
public static void asynStaticMethod(String block){
for(int i =0;i<COUNT;i++){
System.out.println("静态异步"+block+"并发"+i);
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for(int j= 0;j<10;j++){
int finalJ = j;
executorService.execute(() -> {
SyncStaticMethod.asynStaticMethod(""+ finalJ);
});
}
}
}
不添加关键字静态方法
静态异步0并发0
静态异步0并发1
静态异步0并发2
静态异步0并发3
静态异步0并发4
静态异步0并发5
静态异步0并发6
静态异步0并发7
静态异步0并发8
静态异步0并发9
静态异步1并发0
静态异步1并发1
静态异步1并发2
静态异步1并发3
静态异步1并发4
静态异步1并发5
静态异步1并发6
静态异步1并发7
静态异步1并发8
静态异步1并发9
静态异步2并发0
静态异步3并发0
静态异步3并发1
静态异步2并发1
静态异步2并发2
静态异步3并发2
静态异步3并发3
静态异步2并发3
静态异步2并发4
静态异步2并发5
静态异步2并发6
静态异步3并发4
静态异步3并发5
静态异步3并发6
静态异步3并发7
静态异步3并发8
静态异步3并发9
静态异步2并发7
静态异步2并发8
静态异步2并发9
静态异步4并发0
静态异步4并发1
静态异步4并发2
静态异步4并发3
静态异步4并发4
静态异步4并发5
静态异步4并发6
静态异步4并发7
静态异步5并发0
静态异步6并发0
静态异步6并发1
静态异步6并发2
静态异步6并发3
静态异步6并发4
静态异步6并发5
静态异步6并发6
静态异步4并发8
静态异步4并发9
静态异步6并发7
静态异步6并发8
静态异步5并发1
静态异步5并发2
静态异步5并发3
静态异步5并发4
静态异步5并发5
静态异步5并发6
静态异步5并发7
静态异步6并发9
静态异步5并发8
静态异步5并发9
静态异步7并发0
静态异步7并发1
静态异步7并发2
静态异步7并发3
静态异步7并发4
静态异步7并发5
静态异步7并发6
静态异步8并发0
静态异步8并发1
静态异步8并发2
静态异步8并发3
静态异步8并发4
静态异步8并发5
静态异步9并发0
静态异步9并发1
静态异步9并发2
静态异步7并发7
静态异步7并发8
静态异步7并发9
静态异步9并发3
静态异步8并发6
静态异步8并发7
静态异步8并发8
静态异步8并发9
静态异步9并发4
静态异步9并发5
静态异步9并发6
静态异步9并发7
静态异步9并发8
静态异步9并发9
一个带有成员变量的demo
public class SyncExample {
static final int clientTotal = 30000;
static final int threadTotal = 300;
static int count = 0;
synchronized void add() {
count++;
}
public static void main(String[] args) throws Exception {
SyncExample syncExample = new SyncExample();
ExecutorService executorService = Executors.newCachedThreadPool();
Semaphore semaphore = new Semaphore(threadTotal);
CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for(int i =0;i<clientTotal;i++){
executorService.execute(()->{
try {
semaphore.acquire();
syncExample.add();
semaphore.release();
} catch (Exception e) {
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
System.out.println("总计执行:"+count);
}
}
总结
synchronized 修饰类型 | 作用范围 | 锁定对象 | 实现 |
---|---|---|---|
作用于代码块 | 大括号{}括起来的代码 | 调用代码块的对象 | synchronized(this){...} |
作用于方法 | 整个方法 | 调用代码块的对象 | public synchronized void xxx(){...} |
作用于静态方法 | 静态方法 | 该类所有对象 | public static synchronized void xxx(){...} |
作用于类 | synchronized后面括号括起来的部分 | 该类所有对象 | synchronized(xxx.class){...} |
注意:继承并不能使子类继承synchronized关键字,synchronized不属于方法声明的一部分。如需同步需要自己再次添加,
并发之synchronized关键字的应用的更多相关文章
- Java并发之synchronized关键字深度解析(二)
前言 本文继续[Java并发之synchronized关键字深度解析(一)]一文而来,着重介绍synchronized几种锁的特性. 一.对象头结构及锁状态标识 synchronized关键字是如何实 ...
- Java并发之synchronized关键字
上篇文章我们主要介绍了并发的基本思想以及线程的基本知识,通过多线程我们可以实现对计算机资源的充分利用,但是在最后我们也说明了多线程给程序带来的两种典型的问题,针对它们,synchronize ...
- Java并发之synchronized关键字和Lock接口
欢迎点赞阅读,一同学习交流,有疑问请留言 . GitHub上也有开源 JavaHouse,欢迎star 引用 当开发过程中,我们遇到并发问题.怎么解决? 一种解决方式,简单粗暴:上锁.将千军万马都给拦 ...
- Java并发之synchronized关键字深度解析(三)
前言 本篇主要介绍一下synchronized的批量重偏向和批量撤销机制,属于深水区,大家提前备好氧气瓶. 上一篇说完synchronized锁的膨胀过程,下面我们再延伸一下synchronized锁 ...
- Java并发之synchronized关键字深度解析(一)
前言 近期研读路神之绝世武学,徜徉于浩瀚无垠知识之海洋,偶有攫取吉光片羽,惶恐未领略其精髓即隐入岁月深处,遂急忙记录一二,顺备来日吹cow之谈资.本小系列为并发之亲儿子-独臂狂侠synchronize ...
- 深入理解Java并发之synchronized实现原理
深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...
- 《提升能力,涨薪可待》—Java并发之Synchronized
Synchronized简介 线程安全是并发编程中的至关重要的,造成线程安全问题的主要原因: 临界资源, 存在共享数据 多线程共同操作共享数据 而Java关键字synchronized,为多线程场景下 ...
- 从JAVA看C#中volatile和synchronized关键字的作用
最近一直在想C#中 volatile关键字到底是用来干什么的?查了很多.NET的文章都是说用volatile修饰的变量可以让多线程同时修改,这是什么鬼... 然后查到了下面这篇JAVA中关于volat ...
- Java多线程系列--“基础篇”04之 synchronized关键字
概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...
随机推荐
- H5新特性之video audio
1.标签 <video src="~~~" autoplay loop controls controlslist="nodownload nofullscreen ...
- Keepalive+nginx实现高可用负载均衡方案
Keepalive+nginx实现高可用负载均衡方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.nginx做高可用工作在第几层? 上个月我发表了一篇keepalive+lv ...
- 记录一个elasticsearch 的索引templates
搞了好长时间终于成了. { "order": 0, "version": 50001, "template": "click.*& ...
- __attribute__ 机制详解
GNU C 的一大特色就是__attribute__ 机制.__attribute__ 可以设置函数属性(Function Attribute).变量属性(Variable Attribute)和类型 ...
- MyBatisPlus环境下使用MyBatis的配置类
通过@Configuration使用MyBatis配置类的资料比较少,大部分都是通过XML的形式.找了好久,最终还是通过官方的文档找到了解决方法:http://www.mybatis.org/spri ...
- Codeforces 264 B. Good Sequences
B. Good Sequences time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- UESTC - 1168 凤神与狗
原题链接 凤神隐居山林,与猫狗为伴.起初,他拥有cc只猫和dd只狗.每天下午他随机从中选择一只出去游玩并且晚上归来.如果他带的是狗,则第二天早上狗的数量增加ww只,否则,猫的数量增加ww只.由于凤神特 ...
- springboot(十二):springboot单元测试、打包部署
单元测试 1.在pom包中添加spring-boot-starter-test包引用 <dependency> <groupId>org.springframework.boo ...
- IntelliJ IDEA AndroidStudio SVN无法使用
1.Cann't Run Program "SVN" 把勾都去掉,结果没有任何反应.2.重新安装TotoriseSVN,设置Svn.exe路径,主要不要勾选Enable Inter ...
- SQL Server 2008“备份集中的数据库备份与现有的数据库不同”解决方法
对于SQL Server 2008,有几个地方是要注意的,比方在还原数据库时,不像2000里边将数据库和文件区分的很细, 统一均为文件,这就使还原的数据库文件制定为. bak.那么想还原2000的数据 ...