All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.coherence.common.util.CommonMonitor Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2022, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * https://oss.oracle.com/licenses/upl.
 */
package com.oracle.coherence.common.util;

/**
 * Common monitors allow for a low-cost means to reduce contention by
 * spreading synchronization over a large number of monitors. An example
 * usage would be to produce an "atomic array" without utilizing the
 * Java 1.5 java.util.concurrent features. For instance to atomically change
 * an element within an array which is being simultaneously updated by
 * multiple threads:
 * 
 * synchronized (getCommonMonitor(System.identityHashCode(aoShared) + i))
 *     {
 *     oOld = aoShared[i];
 *     aoShared[i] = oNew;
 *     }
 * 
* With this approach many threads may concurrently access various array * elements without having to synchronize on the array itself, and contend * with each other. The use of common monitors also avoids the overhead of * allocating a unique monitor per index. This example additionally makes * use of the array's identity hash code to avoid frequent collisions against * other atomic arrays for the same indices. *

* As they are shared, these monitors will apply to any number of unrelated * entities, and as such certain precautions must be employed when using * them. *

    *
  • The holder of a common monitor MUST not synchronize on any other * common monitor. Failure to adhere to this precaution will result in * a deadlock. *
  • Notifications on a common monitor MUST use notifyAll() rather then * notify(), as there may be unrelated threads waiting for notification * on the same monitor which could consume a single notification. Thus * the only way to ensure that the desired thread does receive * notification is to notify all threads waiting on the monitor. *
  • Threads waiting for a notification must protect themselves against * spurious style wake-ups. While this is a general, though often * overlooked part of the normal use of notification, with common * monitors it is far more likely that a thread will be notified due to * an unrelated event. *
  • A thread which is holding synchronization on a common monitor should * avoid blocking operations as this could block unrelated threads which * happen to be utilizing the same common monitor. *
* The ideal number of common monitors in a JVM is one per concurrently * executing thread. As this number is generally unknown the actual number * of monitors is pre-sized based on a multiple of the number of processors * available to the JVM. The value may also be manually specified via the * com.oracle.coherence.common.util.CommonMonitor.monitors system property. * * @author mf 2007.07.05 */ public final class CommonMonitor { // ----- CommonMonitor interface ------------------------------------- /** * Ensure all writes made prior to this call to be visible to any thread * which calls the corresponding readBarrier method. */ public final void writeBarrier() { // read from a non-volatile to avoid a read barrier int n = ++m_nonvolatile; m_barrier = n == -1 ? 0 : n; // write barrier } /** * Ensure all reads made after this call will have visibility to any * writes made prior to a corresponding call to writeBarrier on another * thread. */ public final void readBarrier() { if (m_barrier == -1) // read barrier { // this check should ensure that the compiler does not optimize // out the read throw new IllegalStateException(); } } // ----- static accessors -------------------------------------------- /** * Return the common monitor associated with the specified integer value. * * @param i the common monitor identifier * * @return the associated monitor */ public static CommonMonitor getCommonMonitor(int i) { CommonMonitor[] aMonitors = MONITORS; return aMonitors[(i & 0x7FFFFFFF) % aMonitors.length]; } /** * Return the common monitor associated with the specified long value. * * @param l the common monitor identifier * * @return the associated monitor * * @see #getCommonMonitor(int) */ public static CommonMonitor getCommonMonitor(long l) { CommonMonitor[] aMonitors = MONITORS; return aMonitors[(int) ((l & 0x7FFFFFFFFFFFFFFFL) % aMonitors.length)]; } /** * Return the common monitor associated with the specified object based on * its identity hashCode. * * @param o the object to obtain a common monitor for * * @return the associated monitor * * @see #getCommonMonitor(int) */ public static CommonMonitor getCommonMonitor(Object o) { return getCommonMonitor(System.identityHashCode(o)); } // ----- constants ------------------------------------------------------ /** * An array of common monitors. * * @see #getCommonMonitor(int) */ private static final CommonMonitor[] MONITORS; static { // The total overhead of a common monitor is 8 bytes for a 32 bit JVM // or 12 bytes for a 64 bit JVM. Ideally the number of monitors will // just exceed the number of active threads. Considering that under- // allocating will result in increased contention, while over-allocating // is not particularly expensive. The default is 512 monitors per CPU, or // approximately 4-6KB per CPU. String sMonitors = System.getProperty(CommonMonitor.class.getName() + ".monitors"); int cMonitors = Runtime.getRuntime().availableProcessors() * 512; if (sMonitors != null) { int c = Integer.parseInt(sMonitors); if (c < cMonitors / 8) { // _trace not available yet System.err.println("The specified number of " + c + " common monitors is significantly lower then the recommended " + cMonitors + " and may result in performance degradation."); } cMonitors = c; } MONITORS = new CommonMonitor[cMonitors]; for (int i = 0; i < cMonitors; ++i) { MONITORS[i] = new CommonMonitor(); } } // ----- data members ------------------------------------------------ protected int m_nonvolatile; protected volatile int m_barrier; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy