Race Condition(竞争条件):多个线程访问共享的数据。共享数据最终的结果取决于线程的执行顺序。
Data Race(数据竞争):多个线程访问未经同步访问控制的共享数据,并且至少一个线程是写数据。
解释有点抽象,举个例子。有两个线程分别对共享的变量i赋值,线程1赋值1,线程2赋值2,那么线程1和线程2即构成Race Condition。而这两个线程会导致Data Race。语言表达还是抽象,见代码:
private int x = 0;
public void test() {
Runnable runnable = new Runnable() {
@Override
public void run() {
x = 1;
}
};
Runnable runnable1 = new Runnable() {
@Override
public void run() {
x = 2;
}
};
new Thread(runnable).start();
new Thread(runnable1).start();
}
由于JVM对int 类型的x赋值操作是原子性的,所以最终的结果取决于线程的访问顺序。
如果x的类型不是int
而是long
或者double
呢?情况就变得复杂起来。long
或者double
在Java中占据64个bit,Java对于这两个数据类型的赋值操作并没有原子性保证。所以对于long
或者double
可以看成两个32bit的数据组合起来,那么就会存在某个线程更新一个32位,另一个线程更新另一个32位数据。或者一个线程在更新其中的一个32位,另一个线程在读取这个64位的bit。这样都会导致的结果就是无法预期的。
对于开发中的用的ConcurrentHashMap
也要注意使用的方法,不是使用了ConcurrentHashMap
就可以避免并发问题。仔细看下面的代码:
ConcurrentHashMap<String, String> stringStringConcurrentHashMap = new ConcurrentHashMap<>();
//方法1
if (!stringStringConcurrentHashMap.containsKey("1")) {
stringStringConcurrentHashMap.put("1", "1");
}
//方法2
stringStringConcurrentHashMap.putIfAbsent("1", "1");
上面的方法1和方法2中,只有方法2能在多线程情况下工作正常。
网友评论