diff --git a/vavr/src/main/java/io/vavr/concurrent/FutureImpl.java b/vavr/src/main/java/io/vavr/concurrent/FutureImpl.java index 57bd243ae..f56b2458c 100644 --- a/vavr/src/main/java/io/vavr/concurrent/FutureImpl.java +++ b/vavr/src/main/java/io/vavr/concurrent/FutureImpl.java @@ -25,7 +25,9 @@ import java.util.Objects; import java.util.concurrent.*; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; /** @@ -45,7 +47,7 @@ final class FutureImpl implements Future { /** * Used to synchronize state changes. */ - private final Object lock = new Object(); + private final Lock lock; /** * Indicates if this Future is cancelled @@ -87,8 +89,10 @@ final class FutureImpl implements Future { // single constructor private FutureImpl(Executor executor, Option> value, Queue>> actions, Queue waiters, Computation computation) { + this.lock = new ReentrantLock(); this.executor = executor; - synchronized (lock) { + lock.lock(); + try { this.cancelled = false; this.value = value; this.actions = actions; @@ -98,6 +102,8 @@ private FutureImpl(Executor executor, Option> value, Queue onComplete(Consumer> action) { if (isCompleted()) { perform(action); } else { - synchronized (lock) { + lock.lock(); + try { if (isCompleted()) { perform(action); } else { actions = actions.enqueue((Consumer>) action); } + } finally { + lock.unlock(); } } return this; @@ -362,7 +380,8 @@ boolean tryComplete(Try value) { final Queue>> actions; final Queue waiters; // it is essential to make the completed state public *before* performing the actions - synchronized (lock) { + lock.lock(); + try { if (isCompleted()) { actions = null; waiters = null; @@ -374,6 +393,8 @@ boolean tryComplete(Try value) { this.waiters = null; this.thread = null; } + } finally { + lock.unlock(); } if (waiters != null) { waiters.forEach(this::unlock);