7 ms·
I agree that there are 1000 ways to create concurrency issues in Swift, as shown in the article. However I fail to see how it's worse than most other multithrea
by Matthias247 8y ago
I agree that there are 1000 ways to create concurrency issues in Swift, as shown in the article. However I fail to see how it's worse than most other multithreaded languages. C++, JVM languages, Go, Python - they all don't provide a lot of support for writing correct thread-safe programs.
Swift/Objective-C might even have an edge compared to some of them, due to providing dispatch queues in the standard library - which are fairly easy to reason about, as shown in the article. I see those as better than the average user creating lots of threads on their own, and then try to synchronize things via mutexes. There might be a performance overhead, but I would only look at that after the program is correct.
There might be languages that provide more help here, e.g. Erlang, Haskell or Pony. But those are not mainstream, and might also not good choices for things where Swift is an alternative (client-side applications). Ada might have been better too, with builtin Task and communication constructs, but that falls into a similar category.
Then we have Rust, which might be the thing you are referring to as a better alternative. It is in the sense that it can prevent most threading issues at compile time - I will refrain from saying "all" since people will write unsafe code, and there can still be deadlocks and logical race conditions. However even Rust thought Rust has lots of tools for preventing concurrency issues, it still doesn't have builtin ways for easy concurrent programs - and e.g. for solving the problem that is described in the article. If one would implement the given solution in Rust, there might be lots of fighting with the borrow-checker involved, and potentially the same amount of heap allocations (callbacks isn't a paradigm that works well in Rust). Obviously there are more idiomatic solutions.
- WoodenChair 8y ago> However I fail to see how it's worse than most other multithreaded languages. C++, JVM languages, Go, Python - they all don't provide a lot of support for writing correct thread-safe programs. Swift/Objective-C might even have an edge compared to some of them, due to providing dispatch queues in the standard library - which are fairly easy to reason about, as shown in the article. A couple corrections: - Dispatch Queues are not a part of the Swift standard library. They are part of Grand Central Dispatch which is almost always present where Swift is present but is actually a separate project. - JVM languages, well specifically Java at least, do have synchronization primitives built-in. It's part of the Java language spec. You can mark any method as synchronized for instance and it will automatically be mostly thread-safe.
- Matthias247 8y agoThanks for adding it. I was actually aware of both things. While Java has some builtin syntax (synchronized) for mutexes, as well as the notify/wait methods on Objects, I don't see them as a big step forward in avoiding concurrency issues. Programmers still need to be aware that they need to use those constructs, which is in most cases already the Nr 1 issue. The next step is using them correctly. The JVM ecosystem has a huge number of libraries and APIs that aim to make concurrency easier (java.util.concurrent, RxJava, Quasar, etc). But all those must first be found, and then used correctly. Rust on the other hand will remind users that something is missing. And Go at least shows the a bit higher level channels first, instead of mutexes.
- kjeetgill 8y agoWhile it's true that much of the hard work of not writing data races is still in the users hands it's important to remember that Java having a memory model and specification for locks/volatiles is a VAST improvement over the same situation in most other languages. It expressly defines what operations do and do not imply a causal relationship, guarantees things like no word tearing on volatile longs, that variables can't "logically" be optimized out of existence in the presence of out of thread writes. It's actually pretty great in practice.
- raphlinus 8y agoJVM has two additional advantages over Swift (sorry for repeating) - an actual memory model, and data races can cause logic errors but not the full undefined behavior of LLVM languages.
- pjmlp 8y agoYou can implement synchronized in a couple of lines in Swift, thanks to trailing lambdas.
- oconnor663 8y ago> However even Rust thought Rust has lots of tools for preventing concurrency issues, it still doesn't have builtin ways for easy concurrent programs - and e.g. for solving the problem that is described in the article. Rust's Mutex type seems like it would be a good fit for this situation. Also this kind of callback -- which is executed immediately instead of stored and executed later -- doesn't require any heap allocation. You find callbacks like this in e.g. the scoped threading or rayon::join APIs.