java 线程安全问题

JVM启动之后,操作系统会为JVM进程分配一定的内存空间,这部分内存空间就称为“主内存”。
Java程序的所有工作都由线程来完成,而每个线程都会有一小块内存,称为“工作内存”, Java中的线程在执行的过程中,会先将数据从主内存中复制到线程的工作内存,然后再执行计算,执行计算之后,再把计算结果刷新到“主内存”中。
假如有两个线程,主内存有变量A=0
线程T1从主内存中获取变量A到工作内存后A++;
线程T2从主内存中获取变量A到工作内存后A++;
线程T1和T2 都进行++运算,两个线程的工作内存中的变量值都为1,
然后两条线程把变量刷新到主内存中,两个线程的刷新顺序是随机的 ,所以主内存的值是1,实际变量值应该为2。
这种多个线程访问同一个对象时,调用这个对象的方法得到不正确的结果,这种问题称为线程安全问题。
原子性:
线程的一个操作活多个操作看作一个整体,整体执行完之后,线程2才能执行。
如T1线程从主内存读变量,在工作内存中++,然后刷新到主内存,这个看作为一个整体,整体执行完之后T2才能执行。这样保证原子性就能避免线程安全的问题
在这里插入图片描述

  • 并发问题的解决方式
    • 无锁
      1.局部变量
      局部变量仅存在线程的工作内存中,所以不同线程质检的局部变量不会有交集
      2.不可变对象
      不可变对象,是一经创建就亘古不变的,因此不管有多少线程对它做什么操作都是不变的,例如String对象。两个字符串组合会得到一个新的字符串对象,但是原本的字符串对象不会改变。String s = “Hello”,"Hello"是不可变对象,而不是指引用"Hello"的变量s
      3.ThreadLocal
      ThreadLocal本质是每个线程都有自己的副本,每个线程的副本互补影响,没有关系。每个线程都会从主内存中拷贝一个ThreadLocal类的对象到工作内存中,每个线程拷贝过来后的对象不是同一个对象,每个对象只会在对应的线程中操作,所以不存在共享变量,就不会有线程安全问题
      4.cas原子类
      cas是比较置换的意思,当内存地址中存在的值和旧的预期值一样的时候就会替换为新的预期值。例如典型的"ABA"问题。Java中Atomic为前缀的类,都采用了cas思想,Atomic系列类采用的是乐观锁
    • 有锁
      1.synchronized
      2.ReentrantLock
      以上两者都是悲观锁的策略
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值