Когда выполняется следующий фрагмент кода, я получаю исключения случайным образом.
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
.
Насколько я понимаю, внутри функции getResult мы проверяем и обновляем атомарную переменную aBoolean, и эта операция проверки и обновления является атомарной, но new Store(...).call();
и new Fetch(...).call();
- нет, и поскольку параллельные потоки включают несколько потоков, поэтому существуетсостояние гонки, возникающее при
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()
, как показано нижеи тогда все работало нормально:
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();
У меня есть следующие вопросы:
Это мойправильно ли вы понимаете состояние гонки, как указано выше, и использовал ли я замок так, как он должен быть?
Как еще можно избежать состояния гонки?
Пожалуйста, дайте мне знать ваши мысли.