diff --git a/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntObjectMap.java b/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntObjectMap.java index 78af531a07..735f423ce8 100644 --- a/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntObjectMap.java +++ b/hugegraph-core/src/main/java/org/apache/hugegraph/backend/store/ram/IntObjectMap.java @@ -29,8 +29,8 @@ public final class IntObjectMap implements RamMap { private static final float DEFAULT_INITIAL_FACTOR = 0.25f; private final int maxSize; - private int currentSize; - private Object[] array; + private volatile int currentSize; + private volatile Object[] array; public IntObjectMap(int size) { this.maxSize = size; @@ -79,10 +79,11 @@ private synchronized void expandCapacity() { if (this.currentSize == this.maxSize) { return; } - this.currentSize = Math.min(this.currentSize * 2, this.maxSize); - Object[] newArray = new Object[this.currentSize]; + int newSize = Math.min(this.currentSize * 2, this.maxSize); + Object[] newArray = new Object[newSize]; System.arraycopy(this.array, 0, newArray, 0, this.array.length); this.clear(); this.array = newArray; + this.currentSize = newSize; } } diff --git a/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java b/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java index 3b8071f9f1..d72269a4f5 100644 --- a/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java +++ b/hugegraph-test/src/main/java/org/apache/hugegraph/unit/UnitTestSuite.java @@ -27,6 +27,7 @@ import org.apache.hugegraph.unit.rocksdb.RocksDBCountersTest; import org.apache.hugegraph.unit.rocksdb.RocksDBSessionTest; import org.apache.hugegraph.unit.rocksdb.RocksDBSessionsTest; +import org.apache.hugegraph.unit.store.RamIntObjectMapTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -148,7 +149,10 @@ Int2IntsMapTest.class, IdSetTest.class, IntMapTest.class, - IntSetTest.class + IntSetTest.class, + + /* store */ + RamIntObjectMapTest.class }) public class UnitTestSuite { } diff --git a/hugegraph-test/src/main/java/org/apache/hugegraph/unit/store/RamIntObjectMapTest.java b/hugegraph-test/src/main/java/org/apache/hugegraph/unit/store/RamIntObjectMapTest.java new file mode 100644 index 0000000000..4e9fe4d95b --- /dev/null +++ b/hugegraph-test/src/main/java/org/apache/hugegraph/unit/store/RamIntObjectMapTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package org.apache.hugegraph.unit.store; + +import java.util.concurrent.CountDownLatch; + +import org.apache.hugegraph.backend.store.ram.IntObjectMap; +import org.junit.Assert; +import org.junit.Test; + +public class RamIntObjectMapTest { + + @Test + public void testConcurrency() { + int size = 32; + IntObjectMap map = new IntObjectMap<>(size); + + final int numThreads = 10; + final CountDownLatch startSignal = new CountDownLatch(1); + final CountDownLatch doneSignal = new CountDownLatch(numThreads); + + for (int i = 0; i < numThreads; i++) { + new Thread(() -> { + try { + startSignal.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + for (int j = 0; j < size; j++) { + map.set(j, j); + } + + doneSignal.countDown(); + }).start(); + } + + startSignal.countDown(); + + try { + doneSignal.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + + for (int i = 0; i < numThreads; i++) { + new Thread(() -> { + for (int j = 0; j < size; j++) { + Integer value = map.get(j); + Assert.assertNotNull(value); + } + }).start(); + } + } +}