Android 同步锁死锁,又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)...

之前在将 Memcached 客户端 EnyimMemcached 迁移 .NET Core 时被这个“坑”坑的刻骨铭心(详见以下链接),当时以为只是在构造函数中调用异步方法(注:这里的异步方法都是指基于Task的)才会出线死锁(deadlock)问题。

最近在使用 redis 客户端 StackExchange.Redis 时也遇到了这个问题, 详见 ASP.NET Core中StackExchange.Redis连接redis服务器的问题 。

StackExchange.Redis 中死锁问题发生在下面的代码:

private static ConnectionMultiplexer ConnectImpl(Func multiplexerFactory, TextWriter log)

{

IDisposable killMe = null;

try

{

var muxer = multiplexerFactory();

killMe = muxer;

// note that task has timeouts internally, so it might take *just over* the regular timeout

var task = muxer.ReconfigureAsync(true, false, log, null, "connect");

if (!task.Wait(muxer.SyncConnectTimeout(true)))

{

task.ObserveErrors();

if (muxer.RawConfig.AbortOnConnectFail)

{

throw ExceptionFactory.UnableToConnect("Timeout");

}

}

if (!task.Result) throw ExceptionFactory.UnableToConnect(muxer.failureMessage);

killMe = null;

return muxer;

}

finally

{

if (killMe != null) try { killMe.Dispose(); } catch { }

}

}

ConnectImpl() 是一个同步方法,muxer.ReconfigureAsync() 是一个 async 异步方法。在 Linux 上运行时, task.Wait(muxer.SyncConnectTimeout(true)) 会因为等待超时而返回 false ,从而出现下面的错误:

StackExchange.Redis.RedisConnectionException: It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. Timeout

at StackExchange.Redis.ConnectionMultiplexer.ConnectImpl(Func`1 multiplexerFactory, TextWriter log)

如果改为 task.Wait() ,在 ASP.NET Core 程序中调用时,请求会因为死锁而卡死。

这是一个典型的同步方法调用异步方法在 Wait 时的死锁问题(详见 Don't Block on Async Code),通常的解决方法是使用 .ConfigureAwait(false); (异步任务执行完成时不获取SynchronizationContext)。StackExchange.Redis 的开发者当然知道这一点,在 muxer.ReconfigureAsync()  中调用每一个异步方法时都加上了 .ConfigureAwait(false); 。但我们遇到的实际情况显示,这一招在 .NET Framework 中管用,在 .NET Core 中却不管用,这可能与 .NET Core 在异步机制上的改变有关,比如在异步方法中 System.Threading.SynchronizationContext.Current 的值总是为 null ,详见 ASP.NET Core 1.0 SynchronizationContext 。

这个问题在 Liunx 上很容易出现,而在 Windows 上需要一定的并发请求才会出现。

public IReadOnlyCollection GetAllElements()

{

var blobRef = CreateFreshBlobRef();

// Shunt the work onto a ThreadPool thread so that it's independent of any

// existing sync context or other potentially deadlock-causing items.

var elements = Task.Run(() => GetAllElementsAsync(blobRef)).GetAwaiter().GetResult();

return new ReadOnlyCollection(elements);

}

参考上面的代码,在 StackExchange.Redis 中的 ConnectImpl() 方法中改为 Task.Run() 调用异步方法,死锁问题依旧。

(转)为什么wait(),notify()和notifyAll()必须在同步块或同步方法中调用

我们常用wait(),notify()和notifyAll()方法来进行线程间通信.线程检查一个条件后就行进入等待状态,例如,在“生产者-消费者”模型中,生产者线程发现缓冲区满了就等待,消费者线程通过 ...

一码阻塞,万码等待:ASP.NET Core 同步方法调用异步方法“死锁”的真相

在我们 2015 年开始的从 .NET Framework 向 .NET Core 迁移的工程中,遇到的最大的坑就是标题中所说的--同步方法中调用异步方法发生"死锁".虽然在 .N ...

【坑】Spring中抽象父类属性注入,子类调用父类方法使用父类注入属性

运行环境 idea 2017.1.1 spring 3.2.9.RELEASE 需求背景 需要实现一个功能,该功能有2个场景A.B,大同小异 抽象一个抽象基类Base,实现了基本相同的方法BaseMe ...

深入理解 EF Core:EF Core 写入数据时发生了什么?

阅读本文大概需要 14 分钟. 原文:https://bit.ly/2C67m1C 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能 ...

Redis上踩过的一些坑

来自: http://blog.csdn.net//chenleixing/article/details/50530419 上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DB ...

[转帖]美团在Redis上踩过的一些坑-1.客户端周期性出现connect timeout

美团在Redis上踩过的一些坑-1.客户端周期性出现connect timeout 博客分类: redis 运维 jedisconnect timeoutnosqltcp  转载请注明出处哈:http ...

三分之一的程序猿之社交类app踩过的那些坑

三分之一的程序猿之社交类app踩过的那些坑 万众创新,全民创业.哪怕去年陌生人社交不管融资与否都倒闭了不知道多少家,但是依然有很多陌生人社交应用层出不穷的冒出来.各种脑洞大开,让人拍案叫起. 下面我们 ...

【Fine原创】JMeter分布式测试中踩过的那些坑

最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试执行阶段工具本身对资源的过量消耗给性能测试带来了瓶颈, ...

与webview打交道中踩过的那些坑

随着HTML5被越来越多的用到web APP的开发当中,webview这一个神器便日渐凸显出重要地位.简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页面,css以及js代码 ...

随机推荐

C程序汇编运行模式简析

SJTUBEAR 原创作品转载请注明出处 /MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1. 汇编 ...

MongoDB win安装后无法远程连接访问

mongoDB安装后无法远程连接访问,原因是端口没有开放允许连接的权限 开启允许连接的权限: 管理工具-高级win防火墙

TColor 与 RGB 的转换函数

function RGB2TColor(const R, G, B: Byte): Integer;begin  // convert hexa-decimal values to RGB  Resu ...

Ubuntu无值守安装mysql

1. 使用apt-get -d install 命令下载安装包, 其中-d表示下载不安装. 下载后的deb包放在/var/cache/apt/archives目录 2. 使用dpkg-preconfi ...

Mysql 应该选择什么引擎

对于如何选择存储引擎,可以简答的归纳为一句话:“除非需要用到某些INNODB 不具备的特性,并且没有其他办法可以替代,否则都应该选择INNODB 引擎”.例如:如果要用到全文索引,建议优先考虑INNO ...

16. Linux 文件目录权限

# 文件参数 d:表示是一个目录-:表示这是一个普通的文件l: 表示这是一个符号链接文件,实际上它指向另一个文件b.c:分别表示区块设备和其他的外围设备,是特殊类型的文件s.p:这些文件关系到系统的数 ...

matlab 向量法建数组(推荐)

一.用赋值的方法可以扩展一个已知的数组: arr= 1:1:4; arr(8)=6; 此时,arr = 1 2 3 4 0 0 0 6 arrNew=arr; 此时arrNew = 1 2 3 4 0 ...

MySQL left join操作中 on与where放置条件的区别

优先级 两者放置相同条件,之所以可能会导致结果集不同,就是因为优先级.on的优先级是高于where的. 1 1 首先明确两个概念: LEFT JOIN 关键字会从左表 (table_name1) 那里 ...

Vue.js-10:第十章 - 组件间的数据通信

一.前言 在上一章的学习中,我们继续学习了 Vue 中组件的相关知识,了解了在 Vue 中如何使用组件的 data.prop 选项.在之前的学习中有提到过,组件是 Vue 中的一个非常重要的概念,我们 ...

virtualenv与virtualenvwrapper虚拟环境

python开发之virtualenv与virtualenvwrapper讲解 在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物 ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值