You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2025/05/03 19:54:58 UTC

(commons-pool) 01/02: Operation on the "idleHighWaterMark" shared variable in "ErodingFactor" class is not atomic [org.apache.commons.pool2.PoolUtils$ErodingFactor] At PoolUtils.java:[line 98] AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch POOL_2_X
in repository https://gitbox.apache.org/repos/asf/commons-pool.git

commit 21eaa240d6f05999b78e1c41586bfed48e98d68b
Author: Gary D. Gregory <ga...@gmail.com>
AuthorDate: Sat May 3 09:16:50 2025 -0400

    Operation on the "idleHighWaterMark" shared variable in "ErodingFactor"
    class is not atomic [org.apache.commons.pool2.PoolUtils$ErodingFactor]
    At PoolUtils.java:[line 98] AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE
---
 src/changes/changes.xml                            |  1 +
 .../java/org/apache/commons/pool2/PoolUtils.java   | 24 ++++++++++++++--------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 45f56d1b..d56cd543 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -53,6 +53,7 @@ The <action> type attribute can be add,update,fix,remove.
       Recompute the remaining duration an additional time when we block when exhausted.
     </action>
     <action type="fix" dev="ggregory" due-to="Wei Guo, Gary Gregory">Fix site link from the About page to the Download page, see also #387.</action>
+    <action type="fix" dev="ggregory" due-to="Gary Gregory">Operation on the "idleHighWaterMark" shared variable in "ErodingFactor" class is not atomic [org.apache.commons.pool2.PoolUtils$ErodingFactor] At PoolUtils.java:[line 98] AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE.</action>
     <!-- ADD -->
     <!-- UPDATE -->
     <action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 79 to 81.</action>
diff --git a/src/main/java/org/apache/commons/pool2/PoolUtils.java b/src/main/java/org/apache/commons/pool2/PoolUtils.java
index a6b8b3b5..313cf54b 100644
--- a/src/main/java/org/apache/commons/pool2/PoolUtils.java
+++ b/src/main/java/org/apache/commons/pool2/PoolUtils.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -46,6 +47,9 @@ public final class PoolUtils {
      * frequently.
      */
     private static final class ErodingFactor {
+
+        private static final float MAX_INTERVAL = 15f;
+
         /** Determines frequency of "erosion" events */
         private final float factor;
 
@@ -53,7 +57,9 @@ public final class PoolUtils {
         private transient volatile long nextShrinkMillis;
 
         /** High water mark - largest numIdle encountered */
-        private transient volatile int idleHighWaterMark;
+        private transient volatile int idleHighWaterMark = 1;
+
+        private final ReentrantLock lock = new ReentrantLock();
 
         /**
          * Creates a new ErodingFactor with the given erosion factor.
@@ -63,8 +69,7 @@ public final class PoolUtils {
          */
         private ErodingFactor(final float factor) {
             this.factor = factor;
-            nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor
-            idleHighWaterMark = 1;
+            nextShrinkMillis = System.currentTimeMillis() + (long) (90_0000 * factor); // now + 15 min * factor
         }
 
         /**
@@ -95,11 +100,14 @@ public final class PoolUtils {
          */
         public void update(final long nowMillis, final int numIdle) {
             final int idle = Math.max(0, numIdle);
-            idleHighWaterMark = Math.max(idle, idleHighWaterMark);
-            final float maxInterval = 15f;
-            final float minutes = maxInterval +
-                    (1f - maxInterval) / idleHighWaterMark * idle;
-            nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
+            lock.lock();
+            try {
+                idleHighWaterMark = Math.max(idle, idleHighWaterMark);
+                final float minutes = MAX_INTERVAL + (1f - MAX_INTERVAL) / idleHighWaterMark * idle;
+                nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor);
+            } finally {
+                lock.unlock();
+            }
         }
     }
     /**