[英]Java Concurrency (Multithreading) - parallel() outcomes differ with tryLock()
在下面的代码中 total 总是 45,但 total1 是不可预测的。 我觉得 total 也应该是不可预测的,因为线程不取决于 tryLock() 是否获取锁。 请任何人解释总计和总计1的计算有什么区别。
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*;
import java.util.stream.*;
public class HelloWorld{
private Lock vault = new ReentrantLock();
private int total = 0;
private int total1 = 0;
public void deposit(int value) {
try {
vault.tryLock();
total += value;
}
finally {
vault.unlock();
}
}
public void add(int val) {
total1 += val;
}
public static void main(String[] unused) {
HelloWorld bank = new HelloWorld();
IntStream.range(1, 10)
.parallel()
.forEach(s -> bank.deposit(s));
System.out.println(bank.total); // 45
HelloWorld bank1 = new HelloWorld();
AtomicLong value1 = new AtomicLong(0);
final long[] value2 = {0};
IntStream.iterate(1, i -> 1).limit(100)
.parallel()
.forEach(i -> value1.incrementAndGet());
IntStream.iterate(1, i -> 1).limit(100)
.parallel()
.forEach(i -> ++value2[0]);
IntStream.iterate(1, i -> 1).limit(100)
.parallel()
.forEach(i -> bank1.add(i));
System.out.println(value1+" "+value2[0]+" " +bank1.total1); // 100 94(Unpredictable) 96 (Unpredictable)
}
}
我觉得 total 也应该是不可预测的,因为线程不取决于 tryLock() 是否获取锁。
我认为你是对的......有点。
您的程序似乎允许不同的线程在没有同步的情况下访问total
(即,当vault.tryLock()
碰巧失败时),但仅仅因为它被允许发生,这并不能保证它实际上会发生。
测试与并发相关的错误有时有效,有时无效。 Java 语言规范和标准 Java 库的 javadoc 保证您的程序遵守某些规则时的某些行为,但它们不保证您的程序在违反规则时会“错误地”行为。 他们允许,但他们不保证。
让事情混淆total
和total1
甚至没有计算相同的东西:
total
正在尝试计算1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
total1
正在尝试计算1 + 1 + 1 + 1 + 1 +...
如果我们只考虑线程:
total
调用由锁保护的deposit
方法。total1
调用不受保护的add
方法。 因此total
是可预测的,因为锁意味着一次只有一个线程可以执行添加操作,但total1
是不可预测的,因为许多线程可能同时执行每个添加操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.