1

Will the following code snippet of a synchronized ArrayList work in a multi-threaded environment?

class MyList {
    private final ArrayList<String> internalList = new ArrayList<String>();

    void add(String newValue) {
        synchronized (internalList) {
            internalList.add(newValue);
        }
    }

    boolean find(String match) {
        synchronized (internalList) {
            for (String value : internalList) {
                if (value.equals(match)) {
                    return true;
                }
            }
        }

        return false;
    }
}

I'm concerned that one thread wont be able to see changes by another thread.

3
  • 2
    Is there a reason why you aren't using List.contains(match)? in find()? Commented Jan 6, 2010 at 21:55
  • 1
    Also, I think you are better off using a Set rather than a list. Finding an element in Set is much faster. Commented Jan 6, 2010 at 21:58
  • Just a quick example, the code is a bit contrived. Commented Jan 6, 2010 at 21:58

5 Answers 5

5

Your code will work and is thread-safe but not concurrent. You may want to consider using ConcurrentLinkedQueue or other concurrent thread-safe data structures like ConcurrentHashMap or CopyOnWriteArraySet suggested by notnoop and employ contains method.

class MyList {
    private final ConcurrentLinkedQueue<String> internalList = 
         new ConcurrentLinkedQueue<String>();

    void add(String newValue) {
        internalList.add(newValue);
    }

    boolean find(String match) {
        return internalList.contains(match);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

You should also consider using ConcurrentHashMap or CopyOnWriteArraySet, as those would significantly increase your find operation
Apologies that my code was a bit simplified. The actual code stores objects and need to perform custom action.
3

This should work, because synchronizing on the same object establishes a happens-before relationship, and writes that happen-before reads are guaranteed to be visible.

See the Java Language Specification, section 17.4.5 for details on happens-before.

2 Comments

Thanks, so another thread is guaranteed to see any changes because of the synchronize flushes the array list state?
Actually, this is not a problem with flushing, but with optimizations done by the JIT. The JIT assumes that fields are only modified by the current thread, unless the fields are accessed within a synchronized block, or are volatile. For details, check the JLS.
2

It will work fine, because all access to the list is synchronized. Hovewer, you can use CopyOnWriteArrayList to improve concurrency by avoiding locks (especially if you have many threads executing find).

Comments

2

It will work, but better solution is to create a List by calling Collections.synchronizedList().

Comments

0

You may want to consider using a Set(Tree or Hash) for your data as you are doing lookups by a key. They have methods that will be much faster than your current find method.

HashSet<String> set = new HashSet<String>();
Boolean result = set.contains(match); // O(1) time

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.