对多线程对订单更新竞争的锁机制的实现-初构
来源:互联网 发布:qq晒米软件 编辑:程序博客网 时间:2024/05/16 12:47
做支付宝支付接入时遇到一个问题,对同一个订单,可能同时存在”支付宝服务器异步通知支付结果更新状态“和“用户主动要求发起查询支付结果更新状态"两个过程。因为在查询要用户已支付订单完成后要向其它系统发起交易请求,所以要求对同一订单,两个过程线程必须在更新时是同步执行的。但如果不区分的对整个更新方法加锁,则并发量又上不去。综合考虑,我决定自行实现一个锁机制,要求加锁后的更新方法做到以下要求:1、对不同的订单,执行更新方法的线程是异步执行的;2、对相同的订单,执行更新方法的线程是同步执行的。
初步的代码实现如下:
import java.util.HashMap;/** * 订单锁,当两个线程同时操作同一个oderNo订单时,进入临界区,不同的oderNo不涉及临界区操作.<br> * <p>Long order=1234l;<br> * try{<br> * OrderLock.lock(oderNo);<br> * 同步代码执行……<br> * }finally{<br> * OrderLock.unlock();<br> * }</p> * <br> * */public class OrderLock {private final static HashMap<Long,ObjectLocker<String>> LockerStore=new HashMap<Long,ObjectLocker<String>>();private final static Object lock=new Object();/** * 尝试进入订单号临界区,其它线程若在其后调用此订单号进入,则等待此线程释放锁后才能进入临界区 * @param oderNo 订单号,若已有其它线程使用相同的订单号调用此方法,则需要等待其它线程调用过unlock方法后才能进入临界区 */public static void lock(String oderNo){ObjectLocker<String> objLoc=null;synchronized (lock) {for(Long id : LockerStore.keySet()){if(LockerStore.get(id).equals(oderNo)){objLoc=LockerStore.get(id);}}if(objLoc==null){objLoc=new ObjectLocker<String>(oderNo);}LockerStore.put(Thread.currentThread().getId(), objLoc);}objLoc.lock();}/** * 解除锁,允许其它线程进入订单临界区 */public static void unlock(){ObjectLocker<String> objLoc=null;synchronized (lock) {objLoc=LockerStore.remove(Thread.currentThread().getId());}if(objLoc!=null){objLoc.unlock();}}/** * 对象锁 * * @param <T> */static class ObjectLocker<T> {private final Object locker = new Object();private final static long nullThread = -1;private long threadId = nullThread;private int requestCount=0;private T target;public ObjectLocker(T target) {super();this.target = target;}@Overridepublic boolean equals(Object obj) {if(target==null){return super.equals(obj);}else{return target.equals(obj);}}public void lock() {synchronized (locker) {requestCount++;do {long currThread=Thread.currentThread().getId();if (currThread == threadId || threadId == nullThread) {threadId = currThread;break;}try {locker.wait();} catch (InterruptedException e) {e.printStackTrace();}} while (true);}}public void unlock() {synchronized (locker) {requestCount--;if (Thread.currentThread().getId() == threadId) {threadId = nullThread;locker.notifyAll();}}}public int getReqeustCount(){return requestCount;}}}
初步的测试代码
import java.util.ArrayList;import java.util.HashMap;
public class LockTest {static HashMap<Long,ArrayList<Long>> cache=new HashMap<Long,ArrayList<Long>>();static class TestThread extends Thread{Long orderNo;public TestThread(Long orderNo) {super();this.orderNo = orderNo;}@Overridepublic void run() {try {sleep(2000l);} catch (InterruptedException e) {e.printStackTrace();}for(int i=0;i<60;++i){try{//System.out.println("线程"+getId()+"等待锁"+orderNo+"……");OrderLock.lock(orderNo.toString());cache.get(orderNo).add(getId());try {sleep(20l);} catch (InterruptedException e) {}//System.out.println("线程"+getId()+"获得锁"+orderNo+"……");} finally{cache.get(orderNo).add(getId());OrderLock.unlock();}//System.out.println("线程"+getId()+"释放锁"+orderNo+"……");try {sleep(20l);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {long time0=System.currentTimeMillis();TestThread[] ts=new TestThread[24];cache.put(0l, new ArrayList<Long>());cache.put(1l, new ArrayList<Long>());cache.put(2l, new ArrayList<Long>());cache.put(3l, new ArrayList<Long>());for(int i=0;i<ts.length;++i){ts[i]=new TestThread(i%4l);ts[i].start();}for(int i=0;i<ts.length;++i){try {ts[i].join();} catch (InterruptedException e) {}}System.out.println(System.currentTimeMillis()-time0);for(Long key : cache.keySet()){ArrayList<Long> l=cache.get(key);int len=l.size()/2;for(int i=0;i<len;i++){if(!l.get(2*i).equals(l.get(2*i+1))){System.out.println(2*i);System.out.println(l.get(2*i));System.out.println(l.get(2*i+1));System.out.println(list2String(l));throw new RuntimeException("出现错误");}}//System.out.println(list2String(l));}}static String list2String(ArrayList<Long> l){String tmp="";for(Long i : l){tmp+=i+",";}return tmp;}}
0 0
- 对多线程对订单更新竞争的锁机制的实现-初构
- 解决线程间对共享资源的竞争
- quick-cocos2d-x的热更新机制实现<五>对 framework 的修改
- 多线程之间的竞争
- FileReader搭配FileWriter,更新对抛出的机制做回应
- 对多线程的理解,IOS中有几种实现多线程的方法
- 对多线程的理解
- 对多线程编程和线程同步机制的小理解
- jsessionid传送对session实现机制的影响 jsessionid传送对session实现机制的影响
- 职业的秘密(16)对竞争的态度
- 多线程锁竞争造成的开销
- 3G产业链对我国运营商竞争关系的影响
- 3G产业链对我国运营商竞争关系的影响
- FPGA中对竞争冒险问题的研究(转)
- mybatis使用resultMap实现多对多查询 (需求:商品信息和订单明细有多对多的关系)
- 对多线程的锁的理解
- 从Memcached看锁竞争对服务器性能的巨大影响
- 对您的电子商务订单与Magento优秀的管理
- sun.misc.BASE64Encoder在Eclipse中不能直接使用的原因和解决方案
- c++深拷贝与浅拷贝
- halcon学习之仿射变换1
- Android, 随时随地退出程序ActivityCollector
- UISlider的简单使用,一年不用一次,我是真怕自己忘了怎么用
- 对多线程对订单更新竞争的锁机制的实现-初构
- Seafile服务器配置
- 建立第一个窗体
- 机器人书单与学习资源——导航篇
- 51nod 1428 活动安排问题
- jQuery登录界面,不用跳转页面即可提交post,可以从服务器端获取返回数据
- 快速安装cocoapods
- 用闭包可以解决publish的数据不释放的问题
- 找出两个数组中相同的元素