Java并发竞态条件之处理哪些对象时会发生竞态

前言:做HuaweiDB比赛时,使用了一个CountDownLatch,开16个线程将key-off文件中的key与off写入map中。线程中定义了一个n用来计数,打印n时发现n出现了跳跃从117直接跳跃到238,我就在思考是不是并发时出现其他线程也修改了n的值,因为线程中n要自增。因此就想了解一下处理何种对象时,会出现竞态。

1.局部变量

局部变量是存储在线程自己的栈中的,局部变量不会被多个线程共享。

1.1基础类型的局部变量

线程安全

1.2局部对象引用

引用也被存在线程的栈中,不会被共享,但引用指向的对象,是存放在堆中的,如果这个对象不会被其他方法获得,也不会被非局部变量引用,高级一点的词叫做在该方法中创建的对象不会逃逸,此时这个对象是线程安全的。如果这个对象可能会被其他方法获得,或者是会被非局部变量引用,此时线程是不安全的。在其他线程执行的使用了该对象的方法里,该对象是会被改变的。

 

2.对象成员

对象成员存储在堆上。如果两个线程同时更新同一个对象的同一个成员,此时可能出现错误。因此对象成员也是线程不安全的。

 

3静态变量

静态变量是可以被所有线程都看到的,所有线程都能对他进行修改,因此也是线程不安全的。

举个栗子

一个单例类(懒汉 到需要时才创建对象)当有两个线程A和B都调用了getInstance这个方法时,此时A和B同时调用getInstance,A判断instance为null,在还没有创建对象之前,此时B也判断instance是否为null,因此也创建了一个LazyInitRace对象,并返回结果。这种情况A和B返回的不是同一个对象,如果该类被用于初始化注册表时,就会出现严重的错误,因为返回了不同的实例,有某些注册信息会丢失掉。

public class LazyInitRace{
   private static LazyInitRace instance = null;
   
   public static LazyInitRace getInstance(){
      if(instance == null){
         instance = new LazyInitRace();
      }
      return instance;
   }
}

如何确保线程安全

1.创建不可变的共享对象。

2.加锁。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值