3 ms·
> If you block a thread in the thread pool you’re going to deadlock. I’m actually happy with this decision… it was very much done intentionally to prevent the
by ninkendo 5y ago
> If you block a thread in the thread pool you’re going to deadlock.
I’m actually happy with this decision… it was very much done intentionally to prevent the kind of thread explosion that is all too common in GCD. The criticism of GCD I linked to was very skeptical of actors for this reason; if the implementation decides to add more threads to avoid deadlocks, you get the same performance pitfalls as in GCD, and thankfully that didn’t happen.
In practice, I’ve found that avoiding deadlocks is as simple as grepping for `DispatchSemaphore|DispatchGroup` in your codebase and eliminating them with extreme prejudice. If you stick to Tasks/TaskGroups/Task.sleep, there’s no real possibility of accidentally introducing deadlocks unless you try really hard to do so.
And yeah, logical races can still happen in actors, but it’s easy enough at a glance to tell whether you’ll run into one… if you avoid using `await` in a section of code that needs to run exclusively, you’ll be fine. (Even with `await` calls you may get lucky if there’s no actual suspend point happening, but a quick and dirty rule is just “don’t call await and your code will never be run concurrently.”)
- saagarjha 5y ago> I’ve found that avoiding deadlocks is as simple as grepping for `DispatchSemaphore|DispatchGroup` in your codebase and eliminating them with extreme prejudice. You’d think so but then you realize that framework code you call into might decide to do this and you wouldn’t know until it deadlocked. On a 6-core iPhone 13 this is probably not going to be noticeable, but that’s probably not true on a 2-core iPhone 6s…
- ninkendo 5y agoFramework code you call into can block so long as it makes forward progress. Deadlocks happen if you lock a thread in the shared Concurrency thread pool, and expect some other code running in the same thread pool to do the unlocking. But if you’re calling into framework code which is using GCD, the queues it dispatches into will be run on a separate GCD thread pool. If said framework code is using a semaphore or lock to block your calling (Concurrency) thread, then it stands to reason there’s another thread in the GCD pool which will eventually unlock it. (Or else it’s a deadlock no matter what you do.) I haven’t come across any framework code which violates this, although maybe you’ve run into problems I haven’t.