@Test public void get_shouldBeThreadSafe() throws Exception { int numThreads = 10; CountDownLatch latch = new CountDownLatch(numThreads); ExecutorService executor = Executors.newFixedThreadPool(numThreads); LatchedProvider provider = new LatchedProvider(latch); Lazy<Object> lazy = new Lazy<>(provider); List<Callable<Object>> tasks = new ArrayList<>(numThreads); for (int i = 0; i < numThreads; i++) { tasks.add( () -> { latch.countDown(); return lazy.get(); }); } List<Future<Object>> futures = executor.invokeAll(tasks); assertThat(provider.instantiationCount.get()).isEqualTo(1); Set<Object> createdInstances = new HashSet<>(); for (Future<Object> future : futures) { createdInstances.add(future.get()); } assertThat(createdInstances).hasSize(1); }
@Override public T get() { Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { result = provider.get(); instance = result; provider = null; } } } @SuppressWarnings("unchecked") T tResult = (T) result; return tResult; }
Lazy implements Provider<T> { @Override public T get() { Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { result = provider.get(); instance = result; provider = null; } } } @SuppressWarnings("unchecked") T tResult = (T) result; return tResult; } }
Lazy implements Provider<T> { @Override public T get() { Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { result = provider.get(); instance = result; provider = null; } } } @SuppressWarnings("unchecked") T tResult = (T) result; return tResult; } Lazy(T instance);  Lazy(Provider<T> provider); }
Lazy implements Provider<T> { @Override public T get() { Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { result = provider.get(); instance = result; provider = null; } } } @SuppressWarnings("unchecked") T tResult = (T) result; return tResult; } Lazy(T instance);  Lazy(Provider<T> provider); @Override T get(); }
Lazy implements Provider<T> { @Override public T get() { Object result = instance; if (result == UNINITIALIZED) { synchronized (this) { result = instance; if (result == UNINITIALIZED) { result = provider.get(); instance = result; provider = null; } } } @SuppressWarnings("unchecked") T tResult = (T) result; return tResult; } Lazy(T instance);  Lazy(Provider<T> provider); @Override T get();  }