private static volatile TextTrieMap<TZDBNameInfo> TZDB_NAMES_TRIE = null; private static void prepareFind() { if (TZDB_NAMES_TRIE == null) { synchronized(TZDBTimeZoneNames.class) { if (TZDB_NAMES_TRIE == null) { // loading all names into trie TZDB_NAMES_TRIE = new TextTrieMap<TZDBNameInfo>(true); Set<String> mzIDs = TimeZoneNamesImpl._getAvailableMetaZoneIDs(); for (String mzID : mzIDs) { ... TZDB_NAMES_TRIE.put(std, stdInf); ... } } } } }
new TZDBTimeZoneNames(ULocale.ENGLISH).find("GMT", 0, EnumSet.allOf(NameType.class))
should produce one result. Run this code in 1000 threads: import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import com.ibm.icu.impl.TZDBTimeZoneNames; import com.ibm.icu.text.TimeZoneNames.NameType; import com.ibm.icu.util.ULocale; public class ICU4JTest { public static void main(String... args) throws InterruptedException { final TZDBTimeZoneNames names = new TZDBTimeZoneNames(ULocale.ENGLISH); final AtomicInteger notFound = new AtomicInteger(); final AtomicInteger found = new AtomicInteger(); List<Thread> threads = new ArrayList<>(); for(int i=0; i<1000; i++) { Thread thread = new Thread() { @Override public void run() { int resultSize = names.find("GMT", 0, EnumSet.allOf(NameType.class)).size(); if(resultSize == 0) notFound.incrementAndGet(); else if(resultSize == 1) found.incrementAndGet(); else throw new AssertionError(); } }; thread.start(); threads.add(thread); } for(Thread thread : threads) thread.join(); System.out.println("Not found: "+notFound); System.out.println("Found: "+found); } }
Exception in thread "Thread-383" java.util.ConcurrentModificationException at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:953) at java.util.LinkedList$ListItr.next(LinkedList.java:886) at com.ibm.icu.impl.TextTrieMap$Node.findMatch(TextTrieMap.java:255) at com.ibm.icu.impl.TextTrieMap.find(TextTrieMap.java:100) at com.ibm.icu.impl.TextTrieMap.find(TextTrieMap.java:89) at com.ibm.icu.impl.TZDBTimeZoneNames.find(TZDBTimeZoneNames.java:133) at a.ICU4JTest$1.run(ICU4JTest.java:23) Exception in thread "Thread-447" java.lang.ArrayIndexOutOfBoundsException: 1 at com.ibm.icu.impl.TextTrieMap$Node.matchFollowing(TextTrieMap.java:316) at com.ibm.icu.impl.TextTrieMap$Node.findMatch(TextTrieMap.java:260) at com.ibm.icu.impl.TextTrieMap.find(TextTrieMap.java:100) at com.ibm.icu.impl.TextTrieMap.find(TextTrieMap.java:89) at com.ibm.icu.impl.TZDBTimeZoneNames.find(TZDBTimeZoneNames.java:133) at a.ICU4JTest$1.run(ICU4JTest.java:23) Not found: 430 Found: 568
Almost half of the streams did not find anything, a couple of streams generally fell with the exception. Yes, in a real application, this is unlikely, but if the authors are not interested in a scenario with high competitiveness, then you can do without volatile and DCL. private final Object myInitLock = new Object(); private volatile JPanel myPanels; private EditorsSplitters mySplitters; private void initUI() { if (myPanels == null) { synchronized (myInitLock) { if (myPanels == null) { myPanels = new JPanel(new BorderLayout()); myPanels.setOpaque(false); myPanels.setBorder(new MyBorder()); mySplitters = new EditorsSplitters(this, myDockManager, true); myPanels.add(mySplitters, BorderLayout.CENTER); } } } } public JComponent getComponent() { initUI(); return myPanels; } public EditorsSplitters getMainSplitters() { initUI(); return mySplitters; }
Source: https://habr.com/ru/post/248041/
All Articles