【问题标题】:Start a thread inside an Azure Service Fabric actor?在 Azure Service Fabric 参与者中启动线程?
【发布时间】:2018-08-18 08:00:06
【问题描述】:
我知道 Service Fabric 中的参与者是单线程的。但是假设我在一个actor方法中启动了一个新线程,那么会发生什么?即使生成的线程仍在执行,actor 是否会被停用?
根据documentation,一个actor在一段时间没有被“使用”时会被停用。在这种情况下,“使用”意味着:
- 接听电话
-
IRemindable.ReceiveReminderAsync 被调用
所以看来我开始的新线程没有考虑进去。但也许有人可以证实这一点?
【问题讨论】:
标签:
multithreading
azure
azure-service-fabric
actor
【解决方案1】:
演员只是对象。
Actor 将是deactivated,它可以用于垃圾回收。
操作系统中的实际线程(运行时)保持running,直到它们完成或终止。可以收集它们的托管表示,但这不会影响实际线程。
此外,在 Actor 中生成的线程不会以任何方式被跟踪,因此您有责任自己管理它们的生命周期。
【解决方案2】:
没错。
当你启动一个新线程时,原来的线程(演员)会继续运行并超出范围,而跨线程继续运行。看看会发生什么:
当一个actor接收到一个调用时,处理这个调用的线程会使用一个SemaphoreSlim来获取一个锁来处理actor对象,如果另一个线程已经获取了这个锁,当前线程将等待它的释放,这样它就可以免费继续。
一旦获得锁,线程就会执行并从被调用的方法中返回,然后释放锁,让后面的线程继续执行。
当你跨越一个新线程作为参与者逻辑的一部分时,它只会作为服务进程的一部分运行,但这里的问题是一旦你离开方法范围,你将不再控制这个线程,但它会继续运行,并且对于 Actor 运行时任务已经完成,下一次 Actor 调用将创建另一个线程,并且事情将继续进行。
问题将在以下时间开始:
- 您无法控制正在运行的线程数,您的服务将开始消耗过多内存,SF 可能会尝试跨实例平衡参与者\服务,因为如果移动参与者,它不知道这些线程服务,您的所有线程都将被中止,您将失去这些操作。
- 上一次调用的跨接线程将与新线程竞争下一次actor调用。
- 如果新线程同时使用actor数据继续其他操作,spanned线程和actor线程都会面临并发问题,在没有异常发生的情况下会出现无法轻易调查的奇怪行为。例如,一个线程更改了另一个线程正在使用的值。
- 以及您可能面临的许多其他并发问题
在您可能(认为)需要另一个线程的情况下,您可以:
- 创建另一个参与者来处理任务
- 在队列中创建要由其他服务处理的消息
- 将任务作为参与者调用的一部分执行。