首页 > 开发 > Java > 正文

java基于ConcurrentHashMap设计细粒度实现代码

2024-07-13 10:12:55
字体:
来源:转载
供稿:网友

细粒度锁:

       java/246164.html">java中的几种锁:synchronized,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<String,Object> userMap=new ConcurrentHashMap<String,Object>();	//用户金额map	private static ConcurrentHashMap<String,Integer> moneyMap=new ConcurrentHashMap<String,Integer>();	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----------u1u2-------moneny----------1u1-------moneny----------1-------sleep4s--------u1u3-------moneny----------1-------sleep4s--------u2-------sleep4s--------u3-------awake----------u4u4-------moneny----------1-------awake----------u1u1-------moneny----------2-------awake----------u3u3-------moneny----------2-------awake----------u2u2-------moneny----------2-------sleep4s--------u2-------awake----------u2u2-------moneny----------3-------sleep4s--------u2-------awake----------u2u2-------moneny----------4-------sleep4s--------u2-------awake----------u2u2-------moneny----------5-------sleep4s--------u2-------awake----------u2u2-------moneny----------6

测试结果来看,只有相同userId的线程才会互斥,同步等待;不同userId的线程没有同步

总结

以上就是本文关于java基于ConcurrentHashMap设计细粒度实现代码的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表