java分段锁示例
原文链接 https://blademainer.github.io/2016/04/18/java-multiple-segment-lock/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
Why
读ConcurrentHashMap的时候,我们遇到的一个很大的概念就是Segment
(java8之后只有在调用writeObject方法的方法的时候才会用到segment),该类继承了ReentrantLock
,用于实现分段锁(乐观锁)。处于心痒痒的目的,我也尝试写了个简陋版的分段锁。
How
该Demo实现的比较简单:根据key获取或者创建Lock(获取锁的时候使用double check
),然后使用该锁来同步put或者read(ConcurrentHashMap的读操作使用的volatile,这里不深入)。不足之处还请指正~
What
java实现: github
<!--more-->
package com.xiongyingqi.concurrent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author xiongyingqi
* @version 2016-04-18 16:51
*/
public class MultipleSegmentLock {
private Map<String, ReentrantLock> lockMap = new ConcurrentHashMap<String, ReentrantLock>();
public void write(String key, String value) {
Lock lock = checkLock(key);
lock.lock();
try {
System.out.println("writing... " + key + "=" + value);
try {
// Random random = new Random();
// long time = random.nextInt(10) + 10;
// Thread.sleep(time);
Thread.sleep(10L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("write complete... " + key + "=" + value);
} finally {
lock.unlock();
}
}
public void read(String key) {
Lock lock = checkLock(key);
lock.lock();
try {
System.out.println("reading... " + key);
try {
Thread.sleep(10L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("read complete... " + key);
} finally {
lock.unlock();
}
}
/**
* Getting the lock of the key. Create a {@link ReentrantLock} when not exists.
* <p>Implements with double check</p>
*
* @param key Segment by the key
* @return {@link ReentrantLock}
*/
private Lock checkLock(String key) {
ReentrantLock reentrantLock = lockMap.get(key);
if (reentrantLock == null) {
synchronized (this) {
reentrantLock = lockMap.get(key);
if (reentrantLock == null) {
reentrantLock = new ReentrantLock();
System.out.println(
"lock for " + key + " not exists! so create a lock: " + reentrantLock);
lockMap.put(key, reentrantLock);
return reentrantLock;
}
return reentrantLock;
}
}
return reentrantLock;
}
public static void main(String[] args) {
MultipleSegmentLock multipleSegmentLock = new MultipleSegmentLock();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
multipleSegmentLock.write("key",
"" + i); // synchronous with 'key' and asynchronous with 'key2'
}
}).start();
new Thread(() -> {
for (int i = 100; i < 200; i++) {
multipleSegmentLock.write("key",
"" + i); // synchronous with 'key' and asynchronous with 'key2'
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
multipleSegmentLock.write("key2",
"" + i); // synchronous with 'key2' and asynchronous with 'key'
}
}).start();
new Thread(() -> {
for (int i = 100; i < 200; i++) {
multipleSegmentLock.write("key2",
"" + i); // synchronous with 'key2' and asynchronous with 'key'
}
}).start();
new Thread(() -> {
for (int i = 0; i < 100; i++) {
multipleSegmentLock.read("key");
}
}).start();
// Console out may be:
// ----------------------------------------------------
//lock for key not exists! so create a lock: null
//lock for key2 not exists! so create a lock: null
//writing... key=0
//writing... key2=0
//write complete... key=0
//write complete... key2=0
//writing... key=1
//writing... key2=1
//write complete... key=1
//write complete... key2=1
//writing... key2=2
//writing... key=2
//write complete... key2=2
//write complete... key=2
//writing... key2=3
//writing... key=3
//write complete... key2=3
//write complete... key=3
//... ...
//reading... key
//write complete... key2=49
//read complete... key
//reading... key
//writing... key2=50
//read complete... key
//write complete... key2=50
//reading... key
//writing... key2=51
//read complete... key
//write complete... key2=51
//reading... key
//writing... key2=109
//read complete... key
//write complete... key2=109
//reading... key
//writing... key2=110
//read complete... key
//... ...
//writing... key=194
//write complete... key=194
//writing... key=195
//write complete... key=195
//writing... key=196
//write complete... key=196
//writing... key=197
//write complete... key=197
//writing... key=198
//write complete... key=198
//writing... key=199
//write complete... key=199
// ----------------------------------------------------
}
}