线程安全问题

朴灿烈づ我的快乐病毒、 2024-04-20 04:48 201阅读 0赞

在这里插入图片描述

作者简介: zoro-1,目前大二,正在学习Java,数据结构,mysql,javaee等
作者主页: zoro-1的主页
欢迎大家点赞 ? 收藏 ⭐ 加关注哦!??

线程安全

  • 举一个小李子
    • count++在cpu上的指令
    • 一次错误的并发执行
    • 一次正确的并发执行
  • 线程不安全的原因
  • 线程安全问题如何解决
    • 如何上锁

举一个小李子

  1. public class ThreadText2 {
  2. static int count = 0;
  3. public static void main(String[] args) throws InterruptedException {
  4. Object lock = new Object();
  5. Thread thread = new Thread(() -> {
  6. for (int i = 0; i < 10000; i++) {
  7. count++;
  8. }
  9. });
  10. Thread thread1 = new Thread(() -> {
  11. for (int i = 0; i < 10000; i++) {
  12. count++;
  13. }
  14. });
  15. thread.start();
  16. thread1.start();
  17. thread.join();
  18. thread1.join();
  19. System.out.println(count);
  20. }
  21. }

在这里插入图片描述

我们发现上述代码执行的结果居然是14209,按理来说不应该是20000吗,那是因为这里发生了线程安全问题

count++在cpu上的指令

load:把内存中的数据加载到寄存器中
add:进行++计算
save:把寄存器的值写回内存中

一次错误的并发执行

在这里插入图片描述

首先执行左边的load读取count的值,然后执行右边的load读取count的值,然后右面执行add,然后右面执行save,此时内存中的count的值更新为1,然后执行左面add,然后右面执行save,count中的值还是更新为1,相当于两次++操作实则只执行了一次一样

一次正确的并发执行

在这里插入图片描述

执行左边的load读取count的值,然后左面执行add,然后左面执行save,此时内存中的count的值更新为1,执行右边的load读取count的值1,然后右面执行add,然后右面执行save,此时内存中的count的值更新为2,这样就完美的执行两次了

线程不安全的原因

1.根本原因:操作系统上的线程是随机调度,“抢占式执行”
2.代码结构:多个个线程修改同一个变量
3.直接原因:count++的操作不是原子性的,执行到一般可能会被调出cpu让其他线程有“可乘之机”

线程安全问题如何解决

针对原因三可以将cpu上的三个指令打包成一个整体,这里就引入了锁的概念

1.特点:具有“互斥”,“排他”性
2.目的:将cpu的指令打包为一个具有原子性的操作,并非完全的原子性
3.最核心的规则:如果一个线程针对一个对象加上锁后,其他线程也尝试对这个对象加锁,就会产生阻塞(BLOCKED),一直到前一个线程释放锁为止

比如:去图书馆占座(上锁),中途想学习(被调度)还是休息(被调走)都行,期间别人不能来,走了(释放锁),比人就可以。。。。。

如何上锁

  1. public class ThreadText2 {
  2. static int count = 0;
  3. public static void main(String[] args) throws InterruptedException {
  4. Object lock = new Object();
  5. Thread thread = new Thread(() -> {
  6. for (int i = 0; i < 10000; i++) {
  7. synchronized (lock) {
  8. count++;
  9. }
  10. }
  11. });
  12. Thread thread1 = new Thread(() -> {
  13. for (int i = 0; i < 10000; i++) {
  14. synchronized (lock) {
  15. count++;
  16. }
  17. }
  18. });
  19. thread.start();
  20. thread1.start();
  21. thread.join();
  22. thread1.join();
  23. System.out.println(count);
  24. }
  25. }

在这里插入图片描述

  1. 今天的分享到这里就结束了,感谢大家支持

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,201人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线安全问题

    我们把⼀段代码想象成⼀个房间,每个线程就是要进⼊这个房间的⼈。如果没有任何机制保证,A进⼊房间之后,还没有出来;B 是不是也可以进⼊房间,打断 A 在房间⾥的隐私。这个就...

    相关 线安全问题

    一、线程安全 VS 线程不安全? 线程安全指的是代码若是串行执行和并发执行的结果完全一致,就称为该代码是线程安全的。 若多个线程串行执行(单线程执行)的结果和并发执行的

    相关 线安全问题

    定义 > 首先大家需要思考一下何为线程安全性呢??? 《Java并发编程实战》书中给出定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替

    相关 线安全问题

    线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污