【Java|多线程与高并发】线程安全问题以及synchronized使用实例

news/2024/12/4 18:19:09/

文章目录

  • 1. 前言
  • 2. 线程安全问题演示
  • 3.线程安全问题的原因
  • 4.synchronized关键字
  • 5. 总结

1. 前言

Java多线程环境下,多个线程同时访问共享资源时可能出现的数据竞争和不一致的情况。

线程安全一直都是一个令人头疼的问题.为了解决这个问题,Java为我们提供了很多方式.

  1. synchronized关键字、ReentrantLock类等。
  2. 使用线程安全的数据结构,例如ConcurrentHashMap、ConcurrentLinkedQueue等,避免共享资源
  3. 使用volatile关键字保证内存可见性等方法。

本文主要介绍synchronized关键字
在这里插入图片描述

2. 线程安全问题演示

多线程环境下可能会产生的问题
先看下面这个Test类:

class Test{private int count = 0;public void add(){count++;}public int getCount() {return count;}
}

count是一个普通的成员变量,提供了一个add()方法,让count进行自增
同时提供了一个get方法获取到count的值.

再来看下面这段代码:

public class Demo8 {private static Test test = new Test();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {test.add();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {test.add();}});t1.start();t2.start();t1.join();t2.join();System.out.println(test.getCount());}
}

创建了一个Test类的实例,同时创建两个线程.
让这两个线程各调用50000次Test实例的add()方法,最后输出count的值.

按理来说应该是count的值应该是100000.

运行结果:
在这里插入图片描述
在这里插入图片描述
可以看到运行结果不是100000,而是比100000小. 而且两次运行的结果还不一样.
这就是一个典型的线程安全问题

3.线程安全问题的原因

上述问题产生的原因:
这里的原因主要是 count++操作,count++是三条指令在CPU上执行的.
count++可以分为3个步骤:
在这里插入图片描述

  1. 由于当前是两个线程同时修改同一份变量
  2. 且修改操作不是原子的
  3. 加上线程之间调度的不确定性

上述三条原因导致了这两个线程执行count++操作时,执行的顺序会有多种情况.
例如:
在这里插入图片描述
ps: 这只是其中的一种情况

如果是这种情况会导致什么呢?

看这张图:
在这里插入图片描述
t2线程已经修改过count的值了,但是由于t1并没有获取到count最新的值,因此t1只是在原来读到的count值得基础上进行修改.

因此虽然是执行了两次count++操作,但是真正执行完的效果只有一次count++.这也就是为什么count的值小于100000的原因了.

如果想要让执行完的结果为100000,那么就需要使用synchronized关键字进行加锁了

4.synchronized关键字

synchronized关键字是用于实现线程同步的机制,可以保证在同一时刻只有一个线程可以访问被synchronized包围的代码块或方法,从而避免了多个线程同时访问共享资源时可能出现的数据竞争和不一致的情况。

以上是一些synchronized关键字的介绍,相比大家也不喜欢看这些定义.

接下来就以我自己的方式为大家讲解:

上述问题的解决:
使用synchronizedcount++操作进行加锁,count++之后再进行解锁

此时一个线程在count++时进行加锁后,另外一个线程想进行修改,是修改不了的.这个线程只能阻塞等待

上面提到了使用synchronized进行加锁,什么是加锁呢?
例如下面这张图:
在这里插入图片描述
之前疫情期间,相比大家核酸都没少做吧.
做核酸一次只能给一个人做,如有当前已经有人在做核酸了,那么下一个人只能等待.只有等前面那个人做完,才能够去做.

这里的做核酸就相当于 count++, 去做核酸就相当于是加锁, 在有人做核酸时,其它人只能等待(阻塞等待).做完离开,就相当于解锁(释放锁)

那么如果使用synchronized进行加锁解决上面的问题呢? .

可以对add方法进行加锁.
在这里插入图片描述
执行add方法时会加锁,执行完add方法会解锁.

修改之后的运行结果就是100000了.
在这里插入图片描述

synchronized关键字可以应用于方法(上述示例)和代码块两种情况:

  1. 修饰方法:将synchronized关键字放在方法声明前,表示该方法是同步方法,只有一个线程可以访问该方法。例如:
public synchronized void method() {// 同步代码块
}
  1. 修饰代码块:将synchronized关键字放在代码块前,表示该代码块是同步代码块,只有一个线程可以执行该代码块。例如:
public void method() {synchronized (锁对象) {// 同步代码块}
}

在Java中任何对象都可以作为"锁对象".这里的锁对象十分关键

两个(多个)线程针对同一个对象进行加锁,才会有锁竞争. 如果不对同一个对象进行加锁,每个线程各执行各的,就不会产生锁竞争.也就不会阻塞等待.

因此使用synchronized的加锁的时候,要考虑清楚对哪段代码进行加锁,锁的代码不同,对执行的效果会有很大的影响.

锁的代码越多,锁的粒度越大/越粗,所得代码越少,锁的粒度越小/越细

synchronized关键字的使用需要注意以下几点:

  1. synchronized关键字只能保证同一个对象的同步代码块或同步方法是互斥的,不同对象的同步代码块或同步方法是不互斥的。
  2. synchronized关键字的使用会降低程序的执行效率,因为它会导致线程的上下文切换和锁的竞争。
  3. synchronized关键字只能保证互斥的访问,不能保证线程安全,需要结合其他机制来保证线程安全,例如使用volatile关键字、Atomic类、Lock接口等。

5. 总结

synchronized关键字是Java中实现线程同步的重要机制之一,虽然它的使用会带来一定的性能开销,但是在多线程并发访问共享资源时,使用synchronized关键字可以有效地避免数据竞争和不一致的情况,保证程序的正确性和稳定性。
在这里插入图片描述

感谢你的观看!希望这篇文章能帮到你!
专栏: 《从零开始的Java学习之旅》在不断更新中,欢迎订阅!
“愿与君共勉,携手共进!”
在这里插入图片描述


http://www.ppmy.cn/news/292435.html

相关文章

【3步教程】如何使用商城小程序源码打造自己的商城?

作为电商行业的领头人&#xff0c;在移动端上拥有一款独立小程序绝对是不能缺少的&#xff0c;而使用商城小程序源码打造自己的商城则是最佳的选择之一。本文将教您如何在3步之内&#xff0c;快速高效地使用商城小程序源码&#xff0c;打造属于自己的小程序商城。 步骤一&…

Immer编写简洁的更新state逻辑

react官网推荐库use-immer&#xff1a;https://www.npmjs.com/package/use-immer 引入&#xff1a;import { useImmer } from "use-immer"; 优点&#xff1a; 简化代码: 只需要关注需要变动的部分&#xff0c;而 immer 本身将在后台处理其余部分。学习成本和替换代…

【ChatGLM】记录一次Windows部署ChatGLM-6B流程及遇到的问题

文章目录 部署环境文件下载项目文件模型配置文件模型文件 运行demo遇到的问题 部署环境 系统版本&#xff1a;Windows 10 企业版 版本号&#xff1a;20H2 系统类型&#xff1a;64 位操作系统, 基于 x64 的处理器 处理器&#xff1a;Intel Core™ i7-8700 CPU 3.20GHz 3.19 GH…

CAXA 2020电子图板设计从入门到精通视频教程

CAXA 2013电子图板设计从入门到精通视频教程 链接&#xff1a;https://pan.baidu.com/s/1bGzmzhtUtBQt-prGxvbtUQ 提取码&#xff1a;02qd

CAXA电子图版二次开发20190803

本人有多年的CAXA电子图版二次开发经验&#xff0c;参与过国家电网南瑞集团、中石油、龙记集团、欧姆龙集团、港日集团、中集集团、中国五矿、方圆塑机、大连锅炉、金蝶PDM集成CAXA,TEAMCENTER集成CAXA、大连锅炉机械、中国中车、楼梯围栏、CAXA根据图纸出NC代码、CAXA电子与各…

CAXA 电子图板 二次开发 功能定制

本人有多年的CAXA电子图版二次开发经验&#xff0c;参与过国家电网南瑞集团、中石油、龙记集团、欧姆龙集团、港日集团、中集集团、中国五矿、方圆塑机、大连锅炉、金蝶PDM集成CAXA,TEAMCENTER集成CAXA、大连锅炉机械、中国中车、楼梯围栏、CAXA根据图纸出NC代码、CAXA电子与各…

在电子图版CAXA中定义自己的标题栏和图框

用户自定义的标题栏和图框都存放在文件夹&#xff1a;CAXA/Support/CHS下&#xff0c;此文件在安装文件内。 1、 首先打开CAXA 2、 设置幅面为A4&#xff0c;1&#xff1a;1 3、 拷贝一个现有的标题栏&#xff08;也可自绘一个&#xff09; 4、 块打散&#xff08;保证…

掌握未来设计趋势,CAXA CAD 电子图板 2023让你的创意无限发挥!

CAXA CAD电子图板是一款高效便捷的CAD绘图软件&#xff0c;更是许多设计工程师的首选。该软件以其全面的功能和强大的绘图能力已经成为了国内最为流行的设计软件之一。近期&#xff0c;CAXA CAD电子图板2023版在全新升级上线&#xff0c;更加深入的满足了用户多项需求。 首先&a…