.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 ...
随机推荐
- SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)
SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...
- hadoop is running beyond virtual memory limits问题解决
单机搭建了2.6.5的伪分布式集群,写了一个tf-idf计算程序,分词用的是结巴分词,使用standalone模式运行没有任何问题,切换到伪分布式模式运行一直报错: hadoop is running ...
- 在C++98基础上学习C++11新特性
自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...
- python_重写数组
class MyArray: '''All the elements in this array must be numbers''' def __IsNumber(self,n): if not i ...
- 5月11日——IOS下如何检测用户是否安装微信
执行如下代码: var WXApi = plus.ios.import("WXApi"); var isWXInstalled = WXApi.isWXAppInsta ...
- JS方法:数字转换为千分位字符
/** * 数字转为千分位字符 * @param {Number} num * @param {Number} point 保留几位小数,默认2位 */ function parseToThousan ...
- debain 安装nodejs
apt-get update -yapt-get install -y build-essential curl curl -sL https://deb.nodesource.com/setup_8 ...
- String的trim()用于去掉字符串前后的空格
String的trim()可以去掉字符串的前导和后继字符串,即去掉字符串前面和后面的空格. eg:String userName = " good man "; System.ou ...
- 斐波那契数列第n项的值及前n项之和
<script>// 算法题 // 题1:斐波那契数列:1.1.2.3.5.8.13.21...// // 一.斐波那契数列第n项的值 // // 方法一//递归的写法function a ...
- Composer基本安装步骤
Composer是 PHP 世界里用于管理项目依赖的工具. 1,确保安装PHP,检查方法命令行窗口执行php -v,查看是否正常输出版本 php -v 2,下载安装脚本composer-setup.p ...