.net core 并发下的线程安全问题
抱歉,其实内容并不如题!!!真正的题目应该为《.net core 并发下由于注入模式引起的线程安全问题》
背景(写测试demo所出现的异常,供大家学习与拍砖):
.net core webapi项目,做了一个授权的filter(真正的生产项目的话,JWT很棒),单个接口测试没有问题,当用前端在同一个页面调用多个接口的时候,运行服务,打开页面,然后……Exceptions……(真正的开发中大家应该也会遇到)
异常1:An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside OnConfiguring since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
异常2:A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
异常3:Invalid attempt to call Read when reader is closed.
异常4:Unable to cast object of type 'System.Data.ProviderBase.DbConnectionClosedConnecting' to type 'System.Data.SqlClient.SqlInternalConnectionTds'.
异常5:Object reference not set to an instance of an object.
异常6:不允许启动新事务,因为有其他线程正在该会话中运行。
异常7:An error occurred while updating the entries. See the inner exception for details.
尝试运行了N多遍,嗯,挺不稳定的(代码垃圾!),那看看异常吧
一看很容易理解:在前一个操作完成之前,在此上下文中启动第二个操作。任何实例成员都不能保证是线程安全的。就是说,我在用这个上下文的时候,你来抢个屁……
这个可能发生在并发的情况下,同时使用了同一个上下文……那么打开一个页面,为什么会同时使用同一个上下文呢?好吧,在这里要负荆请罪了(可以说是自己的问题)
我在Filter里面有查询,用到数据库上下文<DbContext> 。罪过咯,直接想在Filter里面过滤黑名单,所以查了数据库(这个业务是不合理的,这是一个作死的行为,请谨慎看待,这里做学习讨论之用)。
public class AuthFilterAttribute : ActionFilterAttribute
{ public override void OnActionExecuting(ActionExecutingContext context)
{ base.OnActionExecuting(context);
..... //判断是否在黑名单内
var blackList = _app.GetBlackList();
......
}
}
这里为什么用 ActionFilterAttribute ?是因为测试的时候要监测一下接口运行的整个过程,So……
然后还有一些错是:对象引用未设置为对象的实例。这个错误太常见,不就是对象为Null了吗?但是,未实例化对象在业务逻辑上的情况太多了。我的应该有:
1、没有获取到当前对象,这是.net core,不是.net,不是因为没有new对象。是注入中没有注入成功,获取注入后,没有获取到。(但我本来运行的好好的,是因为一下是打开对接的页面才发生的问题,可以排除了)
2、本来已经实例的对象被回收了……(这可能性嘛……有一定的可能,但发生在哪呢?)
找啊找,其实方向有了,但是自己却没想起来……
其实如果不确定的话,倒是可以先找找别人是怎么说的(不是为了装X,找开发上的问题我是推荐 github 和 stackoverflow 的,大部分的问题都可以找到):


(2)异常 2

虽然以上找的不一定是真正的答案,至少提供了一个方向,并且你至少可以尝试性地去解决一下。这里提供的方向其实很明确:
1、是否应该使用 Scoped 和 Transient 的,你却使用了 Singleton;
2、多线程中使用了 async 却没有配对的使用 await;
至少我找到的关键点是这两个。
那怎么找到并解决这个问题呢,.net core都是注入的,当然 AuthFilterAttribute 也是注入的。跑到 Startup一看,很明显,问题出在哪里了 -- 单例!本应该是Scoped模式的,却用了单例。
那就将 AuthFilterAttribute 换一种注入模式就行啦。

改为

我使用的是Filter,Filter有自己的生命周期,去确认一下:Filter的官方文档
看到一张图!!!(当然你也可以细细研读一下这个文档)如下:

这还不明显?!!!
Filter会被回收的!!!这同样解释了 异常3、4、5、6、7所发生的原因。
OK,问题已经解决了,这是在开发中遇到的问题,可以说是涉及到.net core 本身的运行机制。
我算是一个应用型的程序员,喜欢在应用中学习底层的东西。那么接下来当然就可以扩展 Singleton、Scoped 和 Transient 等知识了。
如不喜,请拍!
.net core 并发下的线程安全问题的更多相关文章
- Core Data 的线程安全问题
前言: 很多小的App只需要一个ManagedContext在主线程就可以了,但是有时候对于CoreData的操作要耗时很久的,比如App开启的时候要载入大量数据,如果都放在主线程,毫无疑问会阻塞UI ...
- ios 单一线程中的Runloop机制会导致线程安全问题吗?
今天在处理多线程突然想到一个问题,多核处理器会不会导致,单一线程中,由runloop分发的2个函数同时执行呢?进而同时修改同一个变量,产生bug? 我做了以下的测试: - (void)viewDidL ...
- Java并发编程基础-线程安全问题及JMM(volatile)
什么情况下应该使用多线程 : 线程出现的目的是什么?解决进程中多任务的实时性问题?其实简单来说,也就是解决“阻塞”的问题,阻塞的意思就是程序运行到某个函数或过程后等待某些事件发生而暂时停止 CPU 占 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- SimpleDateFormat类的线程安全问题和解决方案
摘要:我们就一起看下在高并发下SimpleDateFormat类为何会出现安全问题,以及如何解决SimpleDateFormat类的安全问题. 本文分享自华为云社区<SimpleDateForm ...
- 被我们忽略的HttpSession线程安全问题
1. 背景 最近在读<Java concurrency in practice>(Java并发实战),其中1.4节提到了Java web的线程安全问题时有如下一段话: Servlets a ...
- Java多线程--线程安全问题的相关研究
在刚刚学线程的时候我们经常会碰到这么一个问题:模拟火车站售票窗口售票.代码如下: package cn.blogs.com.isole; /* 模拟火车站售票窗口售票,假设有50张余票 */ publ ...
- struts2学习笔记--线程安全问题小结
在说struts2的线程安全之前,先说一下,什么是线程安全?这是一个网友讲的, 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样 ...
- iOS中的线程安全问题
为了保证线程安全,不会因为多个线程访问造成资源抢夺,出现的运行结果的偏差问题,我们需要使用到线程同步技术,最常用的就是 @synchronized互斥锁(同步锁).NSLock.dispatch_se ...
随机推荐
- 学习CountDownLatch
对比 使用CyclicBarrier 上次用Barrier方式实现了线程等待一组完成,这次用CountDownLatch来实现 我的理解CountDownLatch 采用的方式是计数器方式,每执行完一 ...
- Mybatis批量更新数据库与批量插入数据库(以oracle为例)
一.批量更新 1.普通写法(一条记录update一次,性能比较差,容易造成阻塞.不建议使用) <update id="updateBatch" parameterType=& ...
- Python_字符串之删除空白字符或某字符或字符串
''' strip().rstrip().lstrip()分别用来删除两端.右端.左端.连续的空白字符或字符集 ''' s='abc ' s2=s.strip() #删除空白字符 print(s2) ...
- 浮点型 float和double类型的内存结构和精度问题
首先引用一个例子在java中可能你会遇到这样的问题: 例:0.99999999f==1f //true 0.9999999f==1f //false 这是超出精度造成的,为了知道为什么会造成这样的问题 ...
- String的valueOf()用于将其它类型转换为字符串
String的valueOf()重载方法可将double类型,int类型,boolean类型以及char数组类型等变量转换为String类变量. 注:String的valueOf()可将char数组转 ...
- SQL关于IN和EXISTS的用法和区别的比较
1.exist,not exist一般都是与子查询一起使用. In可以与子查询一起使用,也可以直接in (a,b.....).2.exist会针对子查询的表使用索引. not exist会对主子查询都 ...
- SQL的操作方法
1 SQL介绍 SQL 是用于访问和处理数据库的标准的计算机语言.关于SQL的具体介绍,我们通过回答如下三个问题来进行. SQL 是什么? SQL,指结构化查询语言,全称是 Structured Qu ...
- 深夜学算法之SkipList:让链表飞
1. 前言 上次写Python操作LevelDB时提到过,有机会要实现下SkipList.摘录下wiki介绍: 跳跃列表是一种随机化数据结构,基于并联的链表,其效率可比拟二叉查找树. 我们知道对于有序 ...
- 图解MySQL索引--B-Tree(B+Tree)
看了很多关于索引的博客,讲的大同小异.但是始终没有让我明白关于索引的一些概念,如B-Tree索引,Hash索引,唯一索引....或许有很多人和我一样,没搞清楚概念就开始研究B-Tree,B+Tree等 ...
- APNs 推送原理及问题
http://bbs.csdn.net/topics/390461996 在 iOS 平台上,大部分应用是不允许在后台运行并连接网络的.在应用没有被运行的时候,只能通过 Apple Push Noti ...