细粒度锁:
java中的几种锁:,ReentrantLock,ReentrantReadWriteLock已基本可以满足编程需求,但其粒度都太大,同一时刻只有一个线程能进入同步块,这对于某些高并发的场景并不适用。比如银行客户a向b转账,c向d转账,假如这两个线程并发,代码其实不需要同步。但是同时有线程3,e向b转账,那么对b而言必须加入同步。这时需要考虑锁的粒度问题,即细粒度锁。
网上搜寻了一些关于java细粒度锁的介绍文章,大部分是提供思路,比如,String.intern()和类ConcurrentHashMap,本人对第三种比较感兴趣,为此研究了下ConcurrentHashMap的源码。基于ConcurrentHashMap设计细粒度大志思路如下:
Map locks = new Map();
List lockKeys = new List();
for (int number : 1 - 10000) {
Object lockKey = new Object();
lockKeys.add(lockKey);
locks.put(lockKey, new Object());
}
public void doSomeThing(String uid) {
Object lockKey = lockKeys.get(uid.hash() % lockKeys.size());
Object lock = locks.get(lockKey);
synchronized(lock) {
// do something
}
}
具体实现如下:
public class LockPool {
//用户map
private static ConcurrentHashMap userMap=new ConcurrentHashMap();
//用户金额map
private static ConcurrentHashMap moneyMap=new ConcurrentHashMap();
public static void main(String[] args) {
LockPool lockPool=new LockPool();
ExecutorService service = Executors.newCachedThreadPool();
service.execute(lockPool.new Boss("u2"));
service.execute(lockPool.new Boss("u1"));
service.execute(lockPool.new Boss("u1"));
service.execute(lockPool.new Boss("u3"));
service.execute(lockPool.new Boss("u2"));
service.execute(lockPool.new Boss("u2"));
service.execute(lockPool.new Boss("u3"));
service.execute(lockPool.new Boss("u2"));
service.execute(lockPool.new Boss("u2"));
service.execute(lockPool.new Boss("u4"));
service.execute(lockPool.new Boss("u2"));
service.shutdown();
}
class Boss implements Runnable{
private String userId;
Boss(String userId){
this.userId=userId;
}
@Override
public void run() {
addMoney(userId);
}
}
public static void addMoney(String userId){
Object obj=userMap.get(userId);
if(obj==null){
obj=new Object();
userMap.put(userId,obj);
}
//obj是与具体某个用户绑定,这里应用了synchronized(obj)的小技巧,而不是同步当前整个对象
synchronized (obj) {
try {
System.out.println("-------sleep4s--------"+userId);
Thread.sleep(4000);
System.out.println("-------awake----------"+userId);
}
catch (InterruptedException e) {
e.printStackTrace();
}
if(moneyMap.get(userId)==null){
moneyMap.put(userId,1);
} else{
moneyMap.put(userId, moneyMap.get(userId)+1);
}
System.out.println(userId+"-------moneny----------"+moneyMap.get(userId));
}
}
}
测试结果:
-------sleep4s--------u2 -------sleep4s--------u1 -------sleep4s--------u3 -------sleep4s--------u4 -------awake----------u2 -------awake----------u3 -------awake----------u1 u2-------moneny----------1 u1-------moneny----------1 -------sleep4s--------u1 u3-------moneny----------1 -------sleep4s--------u2 -------sleep4s--------u3 -------awake----------u4 u4-------moneny----------1 -------awake----------u1 u1-------moneny----------2 -------awake----------u3 u3-------moneny----------2 -------awake----------u2 u2-------moneny----------2 -------sleep4s--------u2 -------awake----------u2 u2-------moneny----------3 -------sleep4s--------u2 -------awake----------u2 u2-------moneny----------4 -------sleep4s--------u2 -------awake----------u2 u2-------moneny----------5 -------sleep4s--------u2 -------awake----------u2 u2-------moneny----------6
测试结果来看,只有相同userId的线程才会互斥,同步等待;不同userId的线程没有同步
原神祈愿模拟器最新版
原神祈愿模拟器手机版是一款完整汉化的趣味原神抽卡模拟小游戏,
宝宝森林美食完整版
宝宝森林美食游戏最新版是一款十分有趣的休闲益智游戏,帮助宝宝
g沙盒仇恨官方英文版(gorebox)
G沙盒仇恨英文原版是一款最近非常火热的沙盒模拟类游戏,在这里
迷你世界测试服最新版2024
迷你世界测试服2021最新版,即迷你世界的先遣服版本,用户能
闪耀暖暖最新版2024
闪耀暖暖手游这是非常好玩的换装手游,游戏内容丰富有趣,游戏环