javathread-synchronizationmapdb

Race condition in synchronized arraylist


I am enclosing processing of list of objects in a synchronized block, but ended up in race condition. Am I using the synchronized block wrongly or is there any other problem with my code? The list is actually instantiated with mapdb.

private static List<MessageHolder> msgHolders;
//messageSequenceDB instantiation
msgHolders = (List<MessageHolder>) messageSequenceDB.indexTreeList("tempStorage", Serializer.JAVA).createOrOpen();


synchronized (msgHolders) {
        System.out.println(Thread.currentThread().getName() +"->"+msgHolders.toString());
        for (MessageHolder holder : msgHolders) {
            if(holder.getStatus().equalsIgnoreCase(STATUS_INITIAL) {
                holder.setStatus(STATUS_DISPATCHED);
                LOGGER.info("MESSAGE SEQUENCER: Message {} dispatched", holder);
                //Remaining code
}}}

I am expecting one object to be processed by only one thread. If the second thread tries to dispatch it, the condition on status should fail. But I am getting output as, few messages are processed by all threads.

Providing sample output here.

pool-12-thread-1->[MessageHolder [key=TradeId.1, message=1, status=Initial], MessageHolder [key=TradeId.2, message=222, status=Initial]]

pool-12-thread-2->[MessageHolder [key=TradeId.2, message=222, status=Initial], MessageHolder [key=TradeId.1, message=1111, status=Initial]]

pool-12-thread-3->[MessageHolder [key=TradeId.2, message=222, status=Initial]]

pool-12-thread-1->[MessageHolder [key=TradeId.1, message=11, status=Initial]]

The message with ID 222 gets processed by all the 3 threads. what should I do to ensure synchronization?


Solution

  • I have solved this by making the field status as volatile.