在 Tasks 中使用 lock() 是否安全?
Is it safe to use lock() with Tasks?
我在这里阅读:
.NET async, can a single thread time-slice between tasks?
除非您显式使用 async/await,否则任务不会 "time-slice" 在后端线程池中的同一线程上。这有保证吗?或者仅仅是当前实施 TPL 的副作用?
如果不能保证,使用时会出现问题 lock()
:
考虑两个任务,它们在释放之前访问 locks
完整 SerialPort 事务(发送消息并接收,或超时)的方法。如果时间分片发生在同一个线程上并且 SerialPort 访问速度足够慢,lock
将无法完成它的工作(让两个调用通过,因为它们在技术上是在同一个线程上)。
是的,只要您不做任何使您的代码(的某些部分)在另一个线程上执行的操作(await
、Task.Run()
、Task.ContinueWith()
、Thread
, …),那么使用 lock
或其他基于线程的同步机制是安全的。
一个可能的例外是,如果您有自定义 TaskScheduler
(例如 TaskScheduler.FromCurrentSynchronizationContext()
)并且您以某种方式让该调度程序尝试执行更多 Task
,而您的 Task
仍在执行(例如 Application.DoEvents()
)。在这种情况下,您的 Task
仍然不会移动到另一个线程,但它可能会暂停,而另一个 Task
在同一线程上执行。不过这种情况应该是极其罕见的。
我在这里阅读:
.NET async, can a single thread time-slice between tasks?
除非您显式使用 async/await,否则任务不会 "time-slice" 在后端线程池中的同一线程上。这有保证吗?或者仅仅是当前实施 TPL 的副作用?
如果不能保证,使用时会出现问题 lock()
:
考虑两个任务,它们在释放之前访问 locks
完整 SerialPort 事务(发送消息并接收,或超时)的方法。如果时间分片发生在同一个线程上并且 SerialPort 访问速度足够慢,lock
将无法完成它的工作(让两个调用通过,因为它们在技术上是在同一个线程上)。
是的,只要您不做任何使您的代码(的某些部分)在另一个线程上执行的操作(await
、Task.Run()
、Task.ContinueWith()
、Thread
, …),那么使用 lock
或其他基于线程的同步机制是安全的。
一个可能的例外是,如果您有自定义 TaskScheduler
(例如 TaskScheduler.FromCurrentSynchronizationContext()
)并且您以某种方式让该调度程序尝试执行更多 Task
,而您的 Task
仍在执行(例如 Application.DoEvents()
)。在这种情况下,您的 Task
仍然不会移动到另一个线程,但它可能会暂停,而另一个 Task
在同一线程上执行。不过这种情况应该是极其罕见的。