diff --git a/core-java-modules/core-java-concurrency-collections-2/pom.xml b/core-java-modules/core-java-concurrency-collections-2/pom.xml
new file mode 100644
index 0000000000..0e5310b9da
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/pom.xml
@@ -0,0 +1,43 @@
+
+ 4.0.0
+ com.baeldung.concurrent.lock
+ core-java-concurrency-collections-2
+ 0.0.1-SNAPSHOT
+
+
+ 1.21
+ 28.2-jre
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${jmh.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${jmh.version}
+
+
+
+
+ src
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java
new file mode 100644
index 0000000000..ceb53ce077
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessBenchmark.java
@@ -0,0 +1,54 @@
+package com.baeldung.concurrent.lock;
+
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.Map;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+@State(Scope.Thread)
+@Fork(value = 2)
+@Warmup(iterations = 0)
+public class ConcurrentAccessBenchmark {
+ static final int SLOTS = 4;
+ static final int THREADS = 10000;
+ static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS;
+ SingleLock singleLock = new SingleLock();
+ StripedLock stripedLock = new StripedLock(BUCKETS);
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @OutputTimeUnit(TimeUnit.MILLISECONDS)
+ public Map singleLockHashMap() throws InterruptedException {
+ return singleLock.doWork(new HashMap(), THREADS, SLOTS);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @OutputTimeUnit(TimeUnit.MILLISECONDS)
+ public Map stripedLockHashMap() throws InterruptedException {
+ return stripedLock.doWork(new HashMap(), THREADS, SLOTS);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @OutputTimeUnit(TimeUnit.MILLISECONDS)
+ public Map singleLockConcurrentHashMap() throws InterruptedException {
+ return singleLock.doWork(new ConcurrentHashMap(), THREADS, SLOTS);
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.Throughput)
+ @OutputTimeUnit(TimeUnit.MILLISECONDS)
+ public Map stripedLockConcurrentHashMap() throws InterruptedException {
+ return stripedLock.doWork(new ConcurrentHashMap(), THREADS, SLOTS);
+ }
+}
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java
new file mode 100644
index 0000000000..ec6d3895da
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/ConcurrentAccessExperiment.java
@@ -0,0 +1,26 @@
+package com.baeldung.concurrent.lock;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import com.google.common.base.Supplier;
+
+public abstract class ConcurrentAccessExperiment {
+
+ public final Map doWork(Map map, int threads, int slots) {
+ CompletableFuture>[] requests = new CompletableFuture>[threads * slots];
+
+ for (int i = 0; i < threads; i++) {
+ requests[slots * i + 0] = CompletableFuture.supplyAsync(putSupplier(map, i));
+ requests[slots * i + 1] = CompletableFuture.supplyAsync(getSupplier(map, i));
+ requests[slots * i + 2] = CompletableFuture.supplyAsync(getSupplier(map, i));
+ requests[slots * i + 3] = CompletableFuture.supplyAsync(getSupplier(map, i));
+ }
+ CompletableFuture.allOf(requests).join();
+
+ return map;
+ }
+
+ protected abstract Supplier> putSupplier(Map map, int key);
+ protected abstract Supplier> getSupplier(Map map, int key);
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/SingleLock.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/SingleLock.java
new file mode 100644
index 0000000000..4dff459df6
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/SingleLock.java
@@ -0,0 +1,36 @@
+package com.baeldung.concurrent.lock;
+
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.google.common.base.Supplier;
+
+public class SingleLock extends ConcurrentAccessExperiment {
+ ReentrantLock lock;
+
+ public SingleLock() {
+ lock = new ReentrantLock();
+ }
+
+ protected Supplier> putSupplier(Map map, int key) {
+ return (()-> {
+ lock.lock();
+ try {
+ return map.put("key" + key, "value" + key);
+ } finally {
+ lock.unlock();
+ }
+ });
+ }
+
+ protected Supplier> getSupplier(Map map, int key) {
+ return (()-> {
+ lock.lock();
+ try {
+ return map.get("key" + key);
+ } finally {
+ lock.unlock();
+ }
+ });
+ }
+}
diff --git a/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/StripedLock.java b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/StripedLock.java
new file mode 100644
index 0000000000..47c47d8813
--- /dev/null
+++ b/core-java-modules/core-java-concurrency-collections-2/src/main/java/com/baeldung/concurrent/lock/StripedLock.java
@@ -0,0 +1,41 @@
+package com.baeldung.concurrent.lock;
+
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+
+import com.google.common.base.Supplier;
+import com.google.common.util.concurrent.Striped;
+
+public class StripedLock extends ConcurrentAccessExperiment {
+ Striped stripedLock;
+
+ public StripedLock(int buckets) {
+ stripedLock = Striped.lock(buckets);
+ }
+
+ protected Supplier> putSupplier(Map map, int key) {
+ return (()-> {
+ int bucket = key % stripedLock.size();
+ Lock lock = stripedLock.get(bucket);
+ lock.lock();
+ try {
+ return map.put("key" + key, "value" + key);
+ } finally {
+ lock.unlock();
+ }
+ });
+ }
+
+ protected Supplier> getSupplier(Map map, int key) {
+ return (()-> {
+ int bucket = key % stripedLock.size();
+ Lock lock = stripedLock.get(bucket);
+ lock.lock();
+ try {
+ return map.get("key" + key);
+ } finally {
+ lock.unlock();
+ }
+ });
+ }
+}