双重加锁检查机制的应用

双重加锁检查和单例
1. 近日,在做项目中实现集合的异步回调功能,使用了双重加锁检查的机制解决同步问题,原先代码如下:

public void obtainNewestInterface(Context context, UpdateBean config, ObtainListener obtainListener) {

if (mUpdateObject == null) {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

这个函数用于获取一个功能的最新对象,如果此对象已经加载完毕(行3),直接回调(行15)。

否则,将回调加入集合中(行5),如果队列没有在运行加载任务(行9),就可以加载启动任务,加载任务的部分代码如下:



@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

mObtainListeners.clear();

}

}

}



加载最新功能对象完成后,将遍历需要加载的集合(行9),一一回调(行11),然后清空(行13)。

这个是没有逻辑问题,但是在多线性同时调用obtainNewestInterface方法的时候,会产生同步的问题,由于没有加入同步锁,会导致集合的对象出现以下错误:

1. 线程A运行至加载完成,遍历回调的时候,线程B运行至mObtainListeners.add(obtainListener);,会出现同步错误。

2. 线程A运行至加载完成,遍历完成的时候,线程B运行至判断是否需要提交任务,这时候size=2,线程A遍历完成,线程B不再提交任务,那么B任务就不会回调

于是加入了锁安全,代码如下:



public void obtainNewestInterface(Context context, UpdateBean config,

ObtainListener obtainListener) {

if (mUpdateObject == null) {

synchronized (mObtainListeners) {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

synchronized (mObtainListeners) {

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

}

mObtainListeners.clear();

}

}

}


这样就解决了如上问题,可是仔细品味一番,新的问题又来了:

1. 线程A执行在遍历,线程B被锁至 if (mUpdateObject == null) {

2.线程B执行遍历完毕,清空集合,此时object不为空,锁解除,线程B进入锁代码,会继续add,此时size=1,会继续提交任务

本质是为了判断object为空就加载一次,回调全部,所以就又加上在锁里面判空,代码如下:


public void obtainNewestInterface(Context context, UpdateBean config,

ObtainListener obtainListener) {

if (mUpdateObject == null) {

synchronized (mObtainListeners) {

//代码加入判空

if (mUpdateObject != null) {

obtainListener.onSucceed(mUpdateObject);

} else {

mObtainListeners.add(obtainListener);

if (mObtainListeners.size() <= 1) {

this.execute(null, context, config);

}

}

}

} else {

obtainListener.onSucceed(mUpdateObject);

}

}

//以下代码不变

@Override

public void onPostExecute(Object result, String taskid) {

if (result != null) {

mUpdateObject = (IAd) result;

synchronized (mObtainListeners) {

for (ObtainListener listener : mObtainListeners) {

listener.onSucceed(mUpdateObject);

}

mObtainListeners.clear();

}

}

}


搞定!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值