温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java中如何实现ConcurrentHashMap设计细粒度

发布时间:2021-07-15 14:38:19 来源:亿速云 阅读:192 作者:小新 栏目:编程语言

小编给大家分享一下java中如何实现ConcurrentHashMap设计细粒度,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

细粒度锁:

       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----------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的线程没有同步

以上是“java中如何实现ConcurrentHashMap设计细粒度”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI