本文介绍了使用并行流和原子变量期间发生的竞争状况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在执行以下代码时,我会以随机方式获取异常.

When the following piece of code is getting executed I am getting exceptions in a random manner.

byte[][] loremIpsumContentArray = new byte[64][];

for (int i = 0; i < loremIpsumContentArray.length; i++)
{
    random.nextBytes(loremIpsumContentArray[i] = new byte[CONTENT_SIZE]);
}

AtomicBoolean aBoolean = new AtomicBoolean(true);
List<Long> resultList = IntStream.range(0, 64* 2)
                                 .parallel()
                                 .mapToObj(i -> getResult(i,
                                                          aBoolean,
                                                          repositoryPath,
                                                          loremIpsumContentArray ))
                                 .collect(Collectors.toList());

getResult函数:

try
{
    Repository repository = repositoryPath.getRepository();
    String path = RepositoryFiles.relativizePath(repositoryPath);

    //return aBoolean.compareAndSet(aBoolean.get(), !aBoolean.get()) ?
    return aBoolean.getAndSet(!aBoolean.get()) ?
                              new Store(new ByteArrayInputStream(loremIpsumContentArray[i / 2]), repository, path, lock).call() :
                              new Fetch(repository, path, lock).call();
}

从上面可以看到,

代码使用并行流,然后调用getResult函数.此外,还涉及一个原子变量.当atomicVariable为true时,调用store函数,为false时,调用fetch函数.

As can be seen from above the code is making use of parallel streams and then calling getResult Function. Also there is an atomic variable involved. When the atomicVariable is true the store function is called and when it is false the fetch function is called.

我的理解是,在getResult函数内部,我们正在检查和更新原子变量aBoolean,并且此检查和更新操作是原子的,但new Store(...).call();new Fetch(...).call();不是,并且由于并行流涉及多个线程,因此存在竞争条件发生在

My understanding is that inside getResult function we are checking and updating atomic variable aBoolean and this check and update operation is atomic but new Store(...).call(); and new Fetch(...).call(); is not and since parallel streams involves multiple threads so there is a race-condition occurring at

return aBoolean.getAndSet(!aBoolean.get()) ?
                          new Store(new ByteArrayInputStream(loremIpsumContentArray[i / 2]), repository, path).call() :
                          new Fetch(repository, path).call();

为了证实我的种族条件理论,我将如下所示的lock分别添加到了new Store(...).call()new Fetch(...).call(),如下所示,然后一切正常:

In order to corroborate my theory of Race condition I added the lock as shown below to both new Store(...).call() and new Fetch(...).call() as shown below and then everything worked fine:

Lock lock = new ReentrantLock();
AtomicBoolean aBoolean = new AtomicBoolean(true);
List<Long> resultList = IntStream.range(0, 64* 2)
                                 .parallel()
                                 .mapToObj(i -> getResult(i,
                                                          aBoolean,
                                                          repositoryPath,
                                                          loremIpsumContentArray,
                                                          lock))
                                 .collect(Collectors.toList());

getResult函数:

return aBoolean.getAndSet(!aBoolean.get()) ?
                          new Store(new ByteArrayInputStream(loremIpsumContentArray[i / 2]), repository, path, lock).call() :
                          new Fetch(repository, path, lock).call();

我有以下问题:

  • 对于上述发生的比赛情况,我的理解是否正确?我是否按应有的方式使用了锁?

  • Is my understanding correct regarding the race condition occurring as mentioned above and have I used the lock in the way they should be?

还有其他避免比赛状况的方法吗?

What are the other ways to avoid the race condition?

请让我知道你的想法.

推荐答案

您的aBoolean.getAndSet(!aBoolean.get())不是原子的.某些线程可能会在!aBoolean.get()和周围的aBoolean.getAndSet之间跳动,这可能会导致竞争状态.

Your aBoolean.getAndSet(!aBoolean.get()) is not atomic.Some thread can hop between !aBoolean.get() and the surrounding aBoolean.getAndSet which might lead to the race condition.

您应该同步块:

boolean whatToExec;
synchronized (aBoolean) {
    whatToExec = aBoolean.get();
    aBoolean.set(!whatToExec);
}
return whatToExec ? ...

FetchStore中,锁定的作用是未知的.如果比赛条件在那里发生,我目前没有答案.

What the lock is good for in Fetch or Store is unknown. If the race condition happens there, I currently have no answer.

这篇关于使用并行流和原子变量期间发生的竞争状况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 15:04