什么是线程安全的?当遇到线程不安全是怎么解决?

什么是线程安全?

线程安全:当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那就称这个对象是线程安全的。(这里指的"线程"安全其实说的是内存的安全)。当系统运行时,如何保证我们的内存的数据时安全的。

在操作系统中,cpu是单线程的,但是又要保证多个程序同时运行,操作系统做出的选择是,给每个进程只能访问自己的内存空间,保证自己信息的安全性。

但是,在每个进程的内存空间,都会有一块特殊的公共区域,这个区域就是我们平常时候说的"堆(内存)",进程内所有的线程都可以访问到这个区域,这就会导致线程不安全。这就是我们所说的线程不安全现象。

         线程一进入堆内存之后执行部分操作,这时,线程一不想运行了,想休息一下,操作系统就会安排线程二进入堆内存中执行,这时堆内存里面就会有两个线程的东西,线程二可能会对线程一的数据造成修改,当线程一再次进入堆中时,数据跟之前不一样,就导致了得到的结果是有误的,这就是线程不安全的。

如何解决线程不安全?

解决的过程就是一个取舍的过程,不同的方案有不同的侧重点。

一.隔离法

1.私有化(局部变量):将未知的隔离

操作系统在进行时,会为每个线程分配一个栈,这个栈是每个线程独有的,如果某些数据只有某个线程才会使用,我们就可以把这些数据存储在独有的栈内存中。常见的就是我们的局部变量。局部变量只有在固定的方法内才可以被使用,这就可以保证其他线程的操作不会影响到我们的局部变量,所以我们的局部变量是安全的。

2.不共享(ThreadLocal):每个人复制一份,各自使用。

通过ThreadLocal可以把每个线程所需要的都拷贝一份,再由每个线程只处理自己的这一份拷贝,而不去影响其他的线程,这就可以造成线程安全。

二.标记法

3.只能看(final)不能摸:只读标记。

可以将公共的数据用final标记,常量是不可修改的,就可以保证我们线程的安全性。

4.先入为主(互斥锁):加锁标记

需要等先运行的数据运行完之后,其他线程才能对该数据进行操作,当线程一进行操作时,会对堆上一个互斥锁,这样B就没办法对堆进行操作,需要等A执行完才可以进入堆操作。举个例子,同一张银行卡,当A在银行存钱,B在手机上付款,如果A先执行,那B手机上付款时就等待A存完钱之后才会显示付款成功。A执行完才能轮到B执行,让数据变得有序起来,才不会导致线程数据发生改变。

三.大胆法

5.失败重试(CAS):先试试,如果遇到错误直接回滚到之前状态。

线程放在堆中并不是一定不安全的,所以我们就可以当他线程二对线程一的数据进行修改时,我们及时停住,回滚到修改之前的数据就可以了。举个例子,同一张银行卡,当A在银行存钱,B在手机上付款,如果A先执行,那B手机上付款时就会显示支付失败。A执行完才能轮到B执行。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值