【并发】并发锁机制-深入理解synchronized(一)
创始人
2024-05-10 03:01:13
0

【并发】并发锁机制-深入理解synchronized(一)

synchronized 基础篇(使用)

一、Java共享内存模型带来的线程安全问题

1. 代码示例

2. 运行结果

3. 问题分析

4. 临界区(Critical Section)

5. 竞态条件(Race Condition)

二、synchronized 的使用

1. 同步普通(实例)方法

2. 同步静态方法

3. 同步this实例对象

4. 同步类对象

5. 同步对象实例

解决之前的共享问题

遗留问题(高级篇种解释)

下一节——synchronized 高级篇(底层原理)​​​​​​​


【并发】并发锁机制-深入理解synchronized(一)

这一篇文章主要介绍synchronized的使用和其底层原理!我将会由浅入深带大家学习synchronized!

synchronized 基础篇(使用)

一、Java共享内存模型带来的线程安全问题

思考: 两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?

1. 代码示例

public class SyncDemo {private static int counter = 0;public static void increment() {counter++;}public static void decrement() {counter--;}public static void main(String[] args) throws InterruptedException {// 线程一Thread t1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {increment();}}, "t1");// 线程二Thread t2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {decrement();}}, "t2");t1.start();t2.start();// main线程 要等到t1、t2线程 运行结束后才会终止t1.join();t2.join();System.out.println("counter = " + counter);}
}

2. 运行结果

以上的结果可能是正数、负数、零(但是为0,基本是不可能出现的!)

3. 问题分析

Java 中对静态变量自增,自减不是原子操作

我们可以查看 i++ i--(i 为静态变量)的 JVM 字节码指令 

i++的JVM 字节码指令

getstatic i    // 获取静态变量i的值

iconst_1     // 将int常量1压入操作数栈

iadd           // 自增

i--的JVM 字节码指令

getstatic i    // 获取静态变量i的值

iconst_1      // 将int常量1压入操作数栈

isub             // 自减

如果单线程情况下,这些JVM指令顺序执行,(不交错)那肯定是没有问题的。

但是,在多线程下,可能会交错运行

4. 临界区(Critical Section)

一个程序运行多个线程本身是没有问题的!问题出在多个线程访问共享资源

多个线程(只)读共享资源其实也没有问题

在多个线程对共享资源读写操作时发生指令交错,就会出现问题!!!

一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区,其共享资源为临界资源

例如,我们上述的代码中的如下部分: 

//临界资源
private static int counter = 0;public static void increment() { //临界区counter++;
}public static void decrement() {//临界区counter--;
}

5. 竞态条件(Race Condition)

多个线程临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

为了避免临界区的竞态条件发生,有多种手段可以达到目的:

  • 阻塞式的解决方案:synchronized(本章节重点),Lock
  • 非阻塞式的解决方案:原子变量(Atomic原子类,CAS)

 需要注意的是,在Java中同步和互斥的场景都是使用synchronized实现的!但它们是有区别的!

  • 互斥是保证临界区的竞态条件发生,同一时刻只能有一个线程执行临界区代码
  • 同步是由于线程执行的先后、顺序不同、需要一个线程等待其它线程运行到某个点 

二、synchronized 的使用

synchronized 同步块是 Java 提供的一种原子性内置锁,Java 中的每个对象都可以把它当作一个同步锁来使用,这些 Java 内置的使用者看不到的锁被称为内置锁,也叫作监视器锁

大致是有 5种用法

1. 同步普通(实例)方法

public synchronized void method() {...
}

2. 同步静态方法

public static synchronized void method() {...
}

3. 同步this实例对象

synchronized(this) {...
}

4. 同步类对象

synchronized(synchronizedDemo.class){...
}

5. 同步对象实例

String lock = "";
synchronized(lock){...
}

解决之前的共享问题

方法一: 

private static int counter = 0;public static synchronized void increment() {counter++;
}public static synchronized void decrement() {counter--;
}

方法二:

private static int counter = 0;
private static String lock = "";public static void increment() {synchronized (lock) {counter++;}
}public static void decrement() {synchronized (lock) {counter--;}
}

synchronized 实际是用对象锁保证了临界区内代码的原子性 

遗留问题(高级篇种解释)

同步实例对象和同步类对象有什么区别? 

这5种方式在性能上面是否有差别? 

下一节——synchronized 高级篇(底层原理)

相关内容

热门资讯

微视频|中国,加速向新   时间,是记录奋斗的见证者,也是锻造辉煌的雕刻师。  回望来路,中国创新的每一步都铿锵有力。  眺...
多彩活动“解锁”文化跨年新场景...   央视网消息:元旦假期,在河北廊坊、福建永春以及浙江义乌都有精彩的活动,给人们带来丰富的假期体验。...
全国各大口岸迎来出入境客流高峰...   央视网消息:元旦期间,全国各大口岸迎来出入境客流高峰,相关部门采取不同措施方便旅客通关。  北京...
新华社评论员:续写中国奇迹新篇...   新华社北京1月1日电 题:续写中国奇迹新篇章  新华社评论员  “我们要锚定目标任务,坚定信心、...
瑞士酒吧火灾约40人丧生 暂无...   新华社日内瓦1月1日电(记者王其冰)瑞士南部瓦莱州警方1日证实,该州阿尔卑斯山区滑雪胜地克朗-蒙...
全年票房超518亿!中国电影市...   国家电影局2026年1月1日公布,2025年电影票房为518.32亿元,同比增长21.95%。国...
海外人士热议习近平新年贺词:中...   中新社北京1月1日电 综合中新社驻外记者报道:新年前夕,中国国家主席习近平发表二〇二六年新年贺词...
新疆阿勒泰:“银发族”驭雪正青...   中新社新疆阿勒泰12月31日电 题:新疆阿勒泰:“银发族”驭雪正青春  中新社记者 蒋文月  正...
这份“年度答卷”,我们共同署名   岁序更替,华章日新。当我们站在时间的交汇点,回首,是携手走过的来路;向前,有无限辽阔的未来。这一...
视频丨多国人士:习主席新年贺词...   多国人士表示,习近平主席的新年贺词重申进一步全面深化改革开放和全球治理倡议,向国际社会传递了积极...