java 细粒度锁

    细粒度锁:

       java中的几种锁:synchronized,ReentrantLock,ReentrantReadWriteLock已基本可以满足编程需求,但其粒度都太大,同一时刻只有一个线程能进入同步块,这对于某些高并发的场景并不适用。比如银行客户a向b转账,c向d转账,假如这两个线程并发,代码其实不需要同步。但是同时有线程3,e向b转账,那么对b而言必须加入同步。这时需要考虑锁的粒度问题,即细粒度锁。

    网上搜寻了一些关于java细粒度锁的介绍文章,大部分是提供思路,比如乐观锁,String.intern()和类ConcurrentHashMap,本人对第三种比较感兴趣,为此研究了下ConcurrentHashMap的源码。基于ConcurrentHashMap设计细粒度大志思路如下:

 

 1 Map locks = new Map();  
 2 List lockKeys = new List();  
 3 for(int number : 1 - 10000) {  
 4    Object lockKey = new Object();  
 5    lockKeys.add(lockKey);  
 6     locks.put(lockKey, new Object());  
 7 }  
 8   
 9 public void doSomeThing(String uid) {  
10    Object lockKey = lockKeys.get(uid.hash() % lockKeys.size());  
11    Object lock = locks.get(lockKey);  
12      
13    synchronized(lock) {  
14       // do something  
15    }  
16 } 

    具体实现如下:

 1 public class LockPool {
 2 
 3     //用户map
 4     private static ConcurrentHashMap<String,Object> userMap=new ConcurrentHashMap<String,Object>();
 5     //用户金额map
 6     private static ConcurrentHashMap<String,Integer> moneyMap=new ConcurrentHashMap<String,Integer>();
 7     
 8     public static void main(String[] args) {
 9         LockPool lockPool=new LockPool();
10         ExecutorService service = Executors.newCachedThreadPool();
11         service.execute(lockPool.new Boss("u2"));
12         service.execute(lockPool.new Boss("u1"));
13         service.execute(lockPool.new Boss("u1"));
14         service.execute(lockPool.new Boss("u3"));
15         service.execute(lockPool.new Boss("u2"));
16         service.execute(lockPool.new Boss("u2"));
17         service.execute(lockPool.new Boss("u3"));
18         service.execute(lockPool.new Boss("u2"));
19         service.execute(lockPool.new Boss("u2"));
20         service.execute(lockPool.new Boss("u4"));
21         service.execute(lockPool.new Boss("u2"));
22         
23         service.shutdown();
24         
25         
26     }
27     
28     class Boss implements Runnable{
29         
30         private String userId;
31         
32         Boss(String userId){
33             this.userId=userId;
34         }
35 
36         @Override
37         public void run() {
38             addMoney(userId);
39         }
40         
41     } 
42     
43     
44     public static void addMoney(String userId){
45         Object obj=userMap.get(userId);
46         if(obj==null){
47             obj=new Object();
48             userMap.put(userId,obj);
49         }
//obj是与具体某个用户绑定,这里应用了synchronized(obj)的小技巧,而不是同步当前整个对象
50 synchronized (obj) { 51 try { 52 System.out.println("-------sleep4s--------"+userId); 53 Thread.sleep(4000); 54 System.out.println("-------awake----------"+userId); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 if(moneyMap.get(userId)==null){ 59 moneyMap.put(userId,1); 60 }else{ 61 moneyMap.put(userId, moneyMap.get(userId)+1); 62 } 63 System.out.println(userId+"-------moneny----------"+moneyMap.get(userId)); 64 } 65 } 66 67 }

  测试结果:

 

——-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锁
    原文地址: http://www.cnblogs.com/xilijava/p/4569333.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞