diff --git a/cdm/core/src/main/java/ucar/nc2/StringLocker.java b/cdm/core/src/main/java/ucar/nc2/StringLocker.java index 5fba06b13a..6f90f77ff1 100644 --- a/cdm/core/src/main/java/ucar/nc2/StringLocker.java +++ b/cdm/core/src/main/java/ucar/nc2/StringLocker.java @@ -1,8 +1,7 @@ package ucar.nc2; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; +import java.util.concurrent.ConcurrentSkipListSet; /** * A list of strings that only allows one thread to use any given value at the same time. @@ -13,13 +12,11 @@ @Deprecated public class StringLocker { - private List stringList = Collections.synchronizedList(new ArrayList<>()); - private boolean waiting; + private final Set stringSet = new ConcurrentSkipListSet<>(); public synchronized void control(String item) { // If the string is in use by another thread then wait() for the other thread - waiting = stringList.contains(item); - while (waiting) { + while (stringSet.contains(item)) { try { wait(); } catch (InterruptedException e) { @@ -27,18 +24,17 @@ public synchronized void control(String item) { } } // Finished waiting so the thread can have the string - stringList.add(item); + stringSet.add(item); } public synchronized void release(String item) { // Tell StringLocker the thread is done with the string - stringList.remove(item); - waiting = false; + stringSet.remove(item); notifyAll(); } public String toString() { - return stringList.toString(); + return stringSet.toString(); } } diff --git a/cdm/core/src/test/java/ucar/nc2/StringLockerTest.java b/cdm/core/src/test/java/ucar/nc2/StringLockerTest.java new file mode 100644 index 0000000000..39d6c01048 --- /dev/null +++ b/cdm/core/src/test/java/ucar/nc2/StringLockerTest.java @@ -0,0 +1,37 @@ +package ucar.nc2; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicReference; + +public class StringLockerTest { + @Test + public void testNonconflicting() throws InterruptedException { + Thread t = new Thread(() -> { + StringLocker locker = new StringLocker(); + locker.control("first"); + locker.control("second"); + locker.release("first"); + locker.release("second"); + }); + t.start(); + t.join(500); + Assert.assertFalse(t.isAlive()); + } + + + @Test + public void testNonconflictingOtherOrder() throws InterruptedException { + Thread t = new Thread(() -> { + StringLocker locker = new StringLocker(); + locker.control("first"); + locker.control("second"); + locker.release("second"); + locker.release("first"); + }); + t.start(); + t.join(500); + Assert.assertFalse(t.isAlive()); + } +}