7080700: numAppContexts is accessed in non-threadsafe way in sun.awt.AppContext
authoranthony
Mon, 16 Apr 2012 18:36:58 +0400
changeset 12412 5966891c3f48
parent 12411 a85a15e74ad5
child 12415 ef319cacbb5a
7080700: numAppContexts is accessed in non-threadsafe way in sun.awt.AppContext Summary: Replace a volatile integer with an AtomicInteger for numAppContexts Reviewed-by: anthony, art, dholmes
jdk/src/share/classes/sun/awt/AppContext.java
--- a/jdk/src/share/classes/sun/awt/AppContext.java	Sun Apr 15 12:58:12 2012 +0300
+++ b/jdk/src/share/classes/sun/awt/AppContext.java	Mon Apr 16 18:36:58 2012 +0400
@@ -46,6 +46,7 @@
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * The AppContext is a table referenced by ThreadGroup which stores
@@ -194,6 +195,15 @@
         return isDisposed;
     }
 
+    /*
+     * The total number of AppContexts, system-wide.  This number is
+     * incremented at the beginning of the constructor, and decremented
+     * at the end of dispose().  getAppContext() checks to see if this
+     * number is 1.  If so, it returns the sole AppContext without
+     * checking Thread.currentThread().
+     */
+    private static final AtomicInteger numAppContexts = new AtomicInteger(0);
+
     static {
         // On the main Thread, we get the ThreadGroup, make a corresponding
         // AppContext, and instantiate the Java EventQueue.  This way, legacy
@@ -209,22 +219,12 @@
                     parentThreadGroup = currentThreadGroup.getParent();
                 }
                 mainAppContext = new AppContext(currentThreadGroup);
-                numAppContexts = 1;
                 return null;
             }
         });
     }
 
     /*
-     * The total number of AppContexts, system-wide.  This number is
-     * incremented at the beginning of the constructor, and decremented
-     * at the end of dispose().  getAppContext() checks to see if this
-     * number is 1.  If so, it returns the sole AppContext without
-     * checking Thread.currentThread().
-     */
-    private static volatile int numAppContexts;
-
-    /*
      * The context ClassLoader that was used to create this AppContext.
      */
     private final ClassLoader contextClassLoader;
@@ -243,7 +243,7 @@
      * @since   1.2
      */
     AppContext(ThreadGroup threadGroup) {
-        numAppContexts++;
+        numAppContexts.incrementAndGet();
 
         this.threadGroup = threadGroup;
         threadGroup2appContext.put(threadGroup, this);
@@ -278,7 +278,7 @@
      * @since   1.2
      */
     public final static AppContext getAppContext() {
-        if (numAppContexts == 1)   // If there's only one system-wide,
+        if (numAppContexts.get() == 1)   // If there's only one system-wide,
             return mainAppContext; // return the main system AppContext.
 
         AppContext appContext = threadAppContext.get();
@@ -513,7 +513,7 @@
             this.table.clear(); // Clear out the Hashtable to ease garbage collection
         }
 
-        numAppContexts--;
+        numAppContexts.decrementAndGet();
 
         mostRecentKeyValue = null;
     }
@@ -804,7 +804,7 @@
                 return getAppContext().isDisposed();
             }
             public boolean isMainAppContext() {
-                return (numAppContexts == 1);
+                return (numAppContexts.get() == 1);
             }
         });
     }