英文:
C# Task async/await vs Golang's goroutines
问题
我已经学习了一段时间的C#和Golang,并尝试比较它们支持异步编程的方式。
关于goroutines,我知道Go运行时可以将goroutines调度到不同的物理/机器线程上运行。如果一个goroutine被阻塞(例如,同步等待I/O),Go运行时可以暂停该goroutine,并释放物理线程来运行其他goroutines。
C#的Task
与goroutine类似,它也是在物理线程之上的一种抽象。然而,在async
Task
内部进行阻塞I/O被认为是一个不好的做法,因为“整个线程将被阻塞,导致死锁”。难道C#运行时不能像goroutines一样暂停被阻塞的async
Task
,并释放物理线程来运行其他的async
Task
吗?
我已经为这个问题苦苦挣扎了一段时间,但找不到解释得更好的公开资料。可以有人帮助我吗?
英文:
I have been learning both C# and Golang for a while and trying to compare the ways they support asynchronous programming.
What I know about goroutines is that the go runtime can schedule the goroutines to run on different physical/machine threads. If a goroutine is blocked (e.g., synchronous waiting for I/O), the go runtime can suspend the goroutine and free the physical threads to run other goroutines.
C# Task
is similar to goroutine in the sense that it is also an abstraction on top of physical threads. However, it is considered a bad idea to do blocking I/O inside an async
Task
because "the entire thread will be blocked, causing deadlock". Can't the C# runtime do something similar to goroutines to suspend the blocked async
Task
and free the physical threads to run other async
Task
s?
I have been struggling for this problem for a while and couldn't find public materials explaining this better. Maybe my understanding is not correct. Can someone please help me?
答案1
得分: 2
C#的Task在某种程度上与goroutine相似,因为它也是在物理线程之上的一种抽象。
然而,在async Task中进行阻塞I/O被认为是一个不好的做法,因为"整个线程将被阻塞,导致死锁"。
阻塞不一定会导致死锁,但是阻塞会阻塞调用线程,直到任务完成。这就是整个目的。
C#运行时不能像goroutine那样做类似的操作来挂起被阻塞的async Task并释放物理线程来运行其他async Task吗?
一个async方法可以使用await
来实现你想要的行为。阻塞是专门用于阻塞线程的。从概念上讲,goroutine有点像将每个方法都设为async
并在每个地方隐式使用await
。
在C#运行时对于任何阻塞情况下做类似于goroutine的操作的更一般情况下:由于向后兼容性的原因,C#运行时很难做到这一点。还有很多依赖于"特殊线程"(UI线程、COM STA线程等)的旧代码,采用绿色线程/协程方法会更加困难。Go语言通过创建一个全新的生态系统来避免了向后不兼容的问题。
英文:
> C# Task is similar to goroutine in the sense that it is also an abstraction on top of physical threads.
At an extremely high view, yes, they can be similar.
> However, it is considered a bad idea to do blocking I/O inside an async Task because "the entire thread will be blocked, causing deadlock".
Blocking doesn't necessarily cause deadlocks, but blocking will block the calling thread until the task completes. That's the whole point.
> Can't the C# runtime do something similar to goroutines to suspend the blocked async Task and free the physical threads to run other async Tasks?
An async method can just use await
to get the behavior you want. Blocking is specifically for blocking threads. Conceptually, goroutines are sort of like making every method async
and implicitly using await
everywhere.
In the more general case of the C# runtime doing something similar to goroutines for any blocking: the C# runtime cannot easily do this because of backwards compatibility. There's also a lot of legacy code that depends on "special threads" (UI threads, COM STA threads, etc) where a green threading / coroutine approach would be more difficult. Go has mostly avoided backwards incompatibility concerns by just creating an entirely new ecosystem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论