parent
b48f01d324
commit
34d04156fc
|
@ -0,0 +1,43 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung.concurrent.lock</groupId>
|
||||||
|
<artifactId>lock-striping</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jmh.version>1.21</jmh.version>
|
||||||
|
<guava.version>28.2-jre</guava.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-core</artifactId>
|
||||||
|
<version>${jmh.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
|
<version>${jmh.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.baeldung.concurrent.lock;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Param;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.MILLISECONDS)
|
||||||
|
public class BenchMark {
|
||||||
|
ConcurrentAccessMap accessMyMap;
|
||||||
|
|
||||||
|
@Param({"HashMap", "HashMap with Lock", "HashMap with Striped Lock",
|
||||||
|
"ConcurrentHashMap", "ConcurrentHashMap with Lock", "ConcurrentHashMap with Striped Lock"})
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Setup
|
||||||
|
public void setup() {
|
||||||
|
switch (type) {
|
||||||
|
case "HashMap":
|
||||||
|
accessMyMap = new NoLock(getHashMap());
|
||||||
|
break;
|
||||||
|
case "ConcurrentHashMap":
|
||||||
|
accessMyMap = new NoLock(getConcurrentHashMap());
|
||||||
|
break;
|
||||||
|
case "HashMap with Lock":
|
||||||
|
accessMyMap = new CoarseGrained(getHashMap());
|
||||||
|
break;
|
||||||
|
case "ConcurrentHashMap with Lock":
|
||||||
|
accessMyMap = new CoarseGrained(getConcurrentHashMap());
|
||||||
|
break;
|
||||||
|
case "HashMap with Striped Lock":
|
||||||
|
accessMyMap = new LockStriped(getHashMap());
|
||||||
|
break;
|
||||||
|
case "ConcurrentHashMap with Striped Lock":
|
||||||
|
accessMyMap = new LockStriped(getConcurrentHashMap());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getHashMap() {
|
||||||
|
return new HashMap<String,String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getConcurrentHashMap() {
|
||||||
|
return new ConcurrentHashMap<String,String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.Throughput)
|
||||||
|
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||||
|
public void test() throws InterruptedException {
|
||||||
|
accessMyMap.doWork(type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.concurrent.lock;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
public class CoarseGrained extends ConcurrentAccessMap {
|
||||||
|
ReentrantLock lock;
|
||||||
|
|
||||||
|
public CoarseGrained(Map<String, String> map) {
|
||||||
|
super(map);
|
||||||
|
lock = new ReentrantLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> putSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
done = lock.tryLock();
|
||||||
|
}
|
||||||
|
map.put("key" + x, "value" + x);
|
||||||
|
lock.unlock();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> getSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
done = lock.tryLock();
|
||||||
|
}
|
||||||
|
map.get("key" + x);
|
||||||
|
lock.unlock();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.concurrent.lock;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
public abstract class ConcurrentAccessMap {
|
||||||
|
static final int SLOTS = 4;
|
||||||
|
static final int THREADS = 10000;
|
||||||
|
static final int BUCKETS = Runtime.getRuntime().availableProcessors() * SLOTS;
|
||||||
|
private CompletableFuture<?>[] requests;
|
||||||
|
Map<String, String> map;
|
||||||
|
|
||||||
|
public ConcurrentAccessMap(Map<String, String> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void doWork(String type) {
|
||||||
|
requests = new CompletableFuture<?>[THREADS * SLOTS];
|
||||||
|
|
||||||
|
for (int i = 0; i < THREADS; i++) {
|
||||||
|
requests[SLOTS * i + 0] = CompletableFuture.supplyAsync(putSupplier(i));
|
||||||
|
requests[SLOTS * i + 1] = CompletableFuture.supplyAsync(getSupplier(i));
|
||||||
|
requests[SLOTS * i + 2] = CompletableFuture.supplyAsync(getSupplier(i));
|
||||||
|
requests[SLOTS * i + 3] = CompletableFuture.supplyAsync(getSupplier(i));
|
||||||
|
}
|
||||||
|
CompletableFuture.allOf(requests).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Supplier<?> putSupplier(int x);
|
||||||
|
protected abstract Supplier<?> getSupplier(int x);
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
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 LockStriped extends ConcurrentAccessMap {
|
||||||
|
Striped<Lock> lock;
|
||||||
|
|
||||||
|
public LockStriped(Map<String, String> map) {
|
||||||
|
super(map);
|
||||||
|
lock = getStripedLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Striped<Lock> getStripedLock() {
|
||||||
|
Striped<Lock> map = Striped.lock(BUCKETS);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> putSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
Lock currentLock = lock.get("key" + x);
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
done = currentLock.tryLock();
|
||||||
|
}
|
||||||
|
map.put("key" + x, "value" + x);
|
||||||
|
currentLock.unlock();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> getSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
Lock currentLock = lock.get("key" + x);
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
done = currentLock.tryLock();
|
||||||
|
}
|
||||||
|
map.get("key" + x);
|
||||||
|
currentLock.unlock();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.baeldung.concurrent.lock;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
public class NoLock extends ConcurrentAccessMap {
|
||||||
|
|
||||||
|
public NoLock(Map<String, String> map) {
|
||||||
|
super(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> putSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
map.put("key" + x, "value" + x);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Supplier<?> getSupplier(int x) {
|
||||||
|
return (()-> {
|
||||||
|
boolean done = false;
|
||||||
|
while(!done) {
|
||||||
|
map.get("key" + x);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue