双重加锁检查和单例
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();
}
}
}
搞定!
分享到:
相关推荐
今天小编就为大家分享一篇关于Java双重检查加锁单例模式的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
QT实现单例模式多线程及双重校验加锁的应用demo
基于对《国务院安委办公室关于实施遏制重特大事故工作指南构建双重预防机制的...结果表明,该系统的实施应用达到了煤矿日常生产中安全风险分级管控与隐患排查治理的要求,为煤炭企业构建双重预防机制提供了良好的示范。
双重预防机制领导小组职责.pdf
危险化学品双重预防机制建设指导手册(2021版).pdf
2022双重预防机制全套台账汇编(156页).doc,这是一份不错的文件
双重预防机制体系文件汇编(全套).docx
安全风险分级管控和隐患排查治理双重预防机制管理制度.doc
山西省煤矿双重预防机制实施指南.doc
双重预防机制模板.pdf
5.指令重排对双重检查加锁模式的影响 1.场景: 面试官:有用过单例模式吗? 我:有有有(自信满满)。 面试官:说说单例模式几种写法? 我:懒汉式和饿汉式,懒汉式巴拉巴拉,饿汉式巴拉巴拉。 面试官:我们都...
应用调查统计及文献综述法探讨化工企业双重预防机制安全管理体系的创新模式,研究了化工企业生产特点、化工安全管理现状及化工企业双重预防机制建设过程中存在的问题,依据双重预防机制的特点及建设要求,对比分析典型...
安全风险分级管控和隐患排查治理双重预防机制实施方案.pdf
以J2EE为开发平台、SSM为开发架构,借助Java语言开发了包括安全风险分级管控、隐患排查治理、安全生产标准化以及系统管理在内的双重预防机制信息系统;采用熵权-灰色关联度评价方法评价系统的风险数据,隐患数据借助...
安全风险管控与隐患排查治理双重预防工作机制考试试题.pdf
双重预防机制体系建设及应用.pdf
双重预防机制建设文件(一企一策)参考模板.doc
工贸公司双重预防机制建设达标文件汇编.docx
造纸企业双重预防机制体系建设模板.docx