并发之synchronized关键字的应用

synchronized关键字理论基础

前两章我们学习了下java内存模型的相关知识, 现在我们来讲讲逢并发必出现的synchronized关键字。

作用

synchronized是Java中的关键字,是一种同步锁。依赖JVM实现。

JMM对synchronized约束

  1. 线程解锁前,必须将变量的最新值刷新回主内存。

  2. 线程加锁时,将情况工作内存中变量的共享值,从而使变量从主内存中读取最新的值。

注意:加锁和解锁的锁必须是同一把锁。

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关键字的应用的更多相关文章

  1. Java并发之synchronized关键字深度解析(二)

    前言 本文继续[Java并发之synchronized关键字深度解析(一)]一文而来,着重介绍synchronized几种锁的特性. 一.对象头结构及锁状态标识 synchronized关键字是如何实 ...

  2. Java并发之synchronized关键字

         上篇文章我们主要介绍了并发的基本思想以及线程的基本知识,通过多线程我们可以实现对计算机资源的充分利用,但是在最后我们也说明了多线程给程序带来的两种典型的问题,针对它们,synchronize ...

  3. Java并发之synchronized关键字和Lock接口

    欢迎点赞阅读,一同学习交流,有疑问请留言 . GitHub上也有开源 JavaHouse,欢迎star 引用 当开发过程中,我们遇到并发问题.怎么解决? 一种解决方式,简单粗暴:上锁.将千军万马都给拦 ...

  4. Java并发之synchronized关键字深度解析(三)

    前言 本篇主要介绍一下synchronized的批量重偏向和批量撤销机制,属于深水区,大家提前备好氧气瓶. 上一篇说完synchronized锁的膨胀过程,下面我们再延伸一下synchronized锁 ...

  5. Java并发之synchronized关键字深度解析(一)

    前言 近期研读路神之绝世武学,徜徉于浩瀚无垠知识之海洋,偶有攫取吉光片羽,惶恐未领略其精髓即隐入岁月深处,遂急忙记录一二,顺备来日吹cow之谈资.本小系列为并发之亲儿子-独臂狂侠synchronize ...

  6. 深入理解Java并发之synchronized实现原理

    深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoader) 深入 ...

  7. 《提升能力,涨薪可待》—Java并发之Synchronized

    Synchronized简介 线程安全是并发编程中的至关重要的,造成线程安全问题的主要原因: 临界资源, 存在共享数据 多线程共同操作共享数据 而Java关键字synchronized,为多线程场景下 ...

  8. 从JAVA看C#中volatile和synchronized关键字的作用

    最近一直在想C#中 volatile关键字到底是用来干什么的?查了很多.NET的文章都是说用volatile修饰的变量可以让多线程同时修改,这是什么鬼... 然后查到了下面这篇JAVA中关于volat ...

  9. Java多线程系列--“基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

随机推荐

  1. POJ1742Coins(多重背包)

    Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 32309   Accepted: 10986 Descripti ...

  2. MyBatis中resultType和resultMap的区别

    resultType和resultMap功能类似  ,都是返回对象信息  ,但是resultMap要更强大一些 ,可自定义.因为resultMap要配置一下,表和类的一一对应关系,所以说就算你的字段名 ...

  3. javascript 面向过程和面向对象

    面向过程 思维方式:把解决问题的关注点,放到解决问题的每一个详细步骤上面. 面向对象 思维方式:把解决问题的关注点,放到解决问题需要的一些对象身上. 创建对象: 对象字面量 使用内置构造对象 封装简单 ...

  4. 【小白技术笔记】保存皮皮虾APP无水印视频到手机相册,只需要三步 [技术干货]

    百万段友回皮皮虾,转身一变,都成了皮友.作为当年的资深段友,今天的皮友的我.看到好视频,经典视频,搞笑视频,就想保存一份到手机相册,然后皮皮虾啊皮皮虾,有个让人很讨厌的地方,保存视频的时候就有皮皮虾的 ...

  5. POJ - 2828 Buy Tickets(线段树单点更新)

    http://poj.org/problem?id=2828 题意 排队买票,依次给出当前人要插队的位置,每个人有个编号,然后问你最后整个的序列是什么? 分析 最后一个人的要插入的位置是确定的,所以逆 ...

  6. 关于Meta标签的一些知识

    1.定义文档的编码格式(H5的标准写法) <meta charset="UTF-8"> 2.声明指定的浏览器以及版本 <meta http-equiv=" ...

  7. 关于JS事件冒泡与JS事件代理(事件委托)

    连接:https://blog.csdn.net/supercoooooder/article/details/52190100 核心代码: <ul id="parentUl" ...

  8. luogu P3924 康娜的线段树

    题面传送门 我们可以画图找规律 这里没图,要看图可以去看M_sea dalao的题解(逃 可以发现单个节点\(i\)对答案的贡献为该节点的点权\(*\frac{1}{2^{dep_i}}\)(\(de ...

  9. jquery 学习(七) - 常用动态效果

    <!--转载于 听说你的代码很6--><!--http://www.jq22.com/webqd2377--> CSS <style> #content #firs ...

  10. SRS服务器搭建,ffmpeg 本地推流,srs从本地拉流

    参考: https://github.com/ossrs/srs/wiki/v2_CN_SampleFFMPEG git clone https://github.com/ossrs/srs cd s ...