什么样的代码存在线程安全问题

说起Java中的线程安全,最容易想到的就是synchronized关键字。CSDN上搜索,可以看到一大堆大神的解释,synchronized修饰代码块、修饰方法、修饰类什么什意思云云,然后贴一大堆代码。
鲜有人提及,到底什么情况下存在线程安全问题?
线程安全:多个线程同一时刻访问同一资源就会有线程安全问题,同一资源可能包括对象、文件等。重点就是“同一时刻、同一资源”。同一时刻是前提,同一资源是触发条件。

存在线程安全的重灾区:IO操作,单例模式,静态成员变量。

1.IO操作。
class A {
public void wirteFile(){
//写文件
}
}
如果在多个线程内创建各自的A对象,并调用其wirteFile方法,虽然是不同的对象有多个wirteFile方法的拷贝独立执行,
但是如果在同一时刻执行,相当于同时写一个文件,就会存在线程安全问题。

2.单例模式。
假设B类是单例的:
class B {
private int count = 0;
public int add(int num){
count = num + 123;
return count;
}
}
如果在多个线程中获取B的实例,执行add方法就可能存在线程安全问题。因为所有线程访问的是同一个B对象,最重要的是count变量
只有一份,同时对其操作肯定会出问题。那么单例模式一定会有线程安全问题吗?其实不一定,还是那句话,重点是“同一”。如果上述代码改成
class B {
public int add(int num){
return num++;
}
}
就不存在线程安全问题。因为各个线程内运行的add方法都有自己的一套临时变量,你可以认为各自拷贝了一套该方法去运行,没有对同一个变量
的操作,当然不会有线程安全问题。

3.静态成员变量。
class C {
public static int num = 0;
public static int getNum(){
num++;
return num;
}
}
这样多个线程无论直接使用类名调用getNum方法还是创建各自的对象调用getNum方法,都会存在线程安全问题,因为静态变量属于类,被所有对象共享。
其实静态成员变量和单例非常相似,他们都是某个成员变量只有一份。单例是只有一个对象所以变量只有一份,静态成员变量是属于整个类,所有对象共享一份。

那么静态方法存不存在线程安全问题?
有可能有,有可能没有。不管多少线程,方法是静态还是非静态,执行某个类的方法都是拷贝一份去过执行的,彼此之间相互隔离。
如果这个静态方法中有对静态变量(静态方法不能含有非静态的成员变量)的操作,就会有线程安全问题,因为静态变量只有一份,各个线程共享。
如果没有静态成员变量,就不存在线程安全问题。

回到最初,线程安全的本质是同时操作同一资源,只有明白什么样的资源属于“只有一份”,才能正确使用synchronized。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值