Code Readability Issues
Several users pointed out issues with the original visual presentation of the code on the page.
- latchkey: "Maybe it is just me, but I can't read the text in the code because the font is nearly white on white."
- masklinn: "the dark mode is truly awful, the code blocks are unreadable...[due to an inline style override]."
- malcolmgreaves: "On mobile (Safari), the lines in the code blocks have different font sizes. They also have different fonts. Some are like 3-4x the size of other lines... the code blocks difficult to follow along."
The author, aoli-al, responded quickly to these issues and indicated that they had implemented fixes.
Artificial Introduction of Sleep Calls
MaxBarraclough highlighted the use of sleep
calls in the code to reliably reproduce a deadlock.
- MaxBarraclough: "Neat to see sleep calls artificially introduced to reliably recreate the deadlock." He also linked to the relevant commit and a bug report for the underlying issue.
Challenges of Concurrent Programming in Java
A significant theme revolves around the inherent difficulties of writing reliable concurrent code in Java due to a lack of protection against race conditions.
- brabel: "Bugs like these are pervasive in languages like Java that give no protection against even the most basic race condition causes. Itโs nearly impossible to write reliable concurrent code. Fray only helps if you actually use it to test everything which is not realistic."
This sentiment extends to a preference for languages with safer concurrency models.
- brabel: "I am convinced, after my last year long struggle to get a highly concurrent Java (actually Kotlin but Kotlin does not add much to help) module at work, that we should only use languages that provide safe concurrency models, like Erlang/Elixir and Rust, or actor-like like Dart and JavaScript, where concurrency is required."
The Elusive "Safe Concurrency Model"
The discussion delves into what constitutes a "safe concurrency model" and whether such a model truly exists.
- gf000: "What is a safe concurrency model? Like, actors can trivially deadlock/livelock, they are no panacea at all, and are trivial to recreate (there are a million java implementations)"
This point leads to broader discussion refuting the idea that there exists some development paradigm that completely superceeds prior practice and makes concurrency easy.
- gf000: "You make it sound like there is some modern development superseding what java has, but that's absolutely not the case."
The limitations of even advanced concurrency techniques like Software Transactional Memory (STM) are considered.
- gf000: "Like even rust is just pretty much a no-overhead
synchronized
on top of an object. It is necessary there, because data races are a fundamental memory safety issue, but Java is immune to that (it has 'safe' data races). Logical bugs can trivially happen in either case - as an easy example even if all your fields are atomically mutated, the whole object may not make sense in certain states, like a date with February the 31st. Rust does nothing against such, and concurrent data structures have ample grounds for realistic examples of the above."
Software Transactional Memory (STM)
STM is brought up as a potential solution, however, the discussion quickly turns critical.
- mrkeen: "STM. The terms 'atomic', 'thread-safe', and 'concurrent' collections are thrown around too loosely for application programmers IMO, for exactly your example above."
- mrkeen: "With STM, you can do two or more things atomically."
- mrkeen: "STM has actual concurrent data structures, where you can write straight-line code like 'if this collection has at least 5 elements, then pop one'."
Critiques of STM are responded to, with the accusation that the original article being referenced was unfair in its assessment.
- mrkeen: "I cannot read this charitably. This is the only reason for, not a damning reason against. It's like doing research & development on condoms, and then realising it's a hopeless failure because they might be used for dangerous activities like sex."
Making Invalid States Unrepresentable
The discussion touches on the principle of designing data structures to prevent invalid states from being represented.
- tialaramex: "\'Make invalid states unrepresentable\' - it's bad design that February the 31st is a thing in your data structure when that's invalid. You can't always avoid this, but it's appalling how bad most people's data structures are."
- nlitened: "I think this phrase sounds good but is not applicable to systems that touch messy reality."
- tialaramex: "But we can do a lot without challenging the messy reality. 61 second minutes are (regrettably) a thing in some time systems, but negative 1 million second minutes are not a thing, there's no need for this to be a signed integer!"
Actor Models and Data Races
The conversation circles back to actor models and how they address data races.
- brabel: "Oh my ... you never seen a proper Actor language, have you?Have a look at Erlang and Pony, for starters. It will open your mind."
- brabel: "Pony doesnโt have locks nor atomic operations or anything like that. Instead, the type system ensures at compile time that your concurrent program can never have data races. So you can write highly concurrent code and never get it wrong."
This approach is contrasted with traditional locking mechanisms.
- brabel: "Both Actor-model languages and Rust (through a surprisingly different path: tracking aliases and lifetimes) do something that's impossible in Java (and most languages): prevent data races due to improper locking (as mentioned above, if your language even has locks and it doesn't make them safe like Rust does, you know you're going to have a really hard time. actor-languages just eliminate locks, and 'manual concurrency', completely)."
However, it is countered that even with actor models, higher-level concurrency issues remain.
- gf000: "Does preventing data races (which is not particularly hard if you are willing to give up certain properties, e.g. just immutability alone solves it) that much of a win?...Like, all the same issues are trivially reproducible at a higher level, with loops within actors' communication that only appear under certain, very dynamic conditions, or a bunch of message passing ending up in an inconsistent state, just not on an 'object' level, but on a 'group of object' level."
Race Conditions and Algorithms
The issue of solving race conditions with algorithms is raised.
- rand_r: "Race conditions are generally solved with algorithms, not the language. For example, defining a total ordering on locks and only acquiring locks in that order to prevent deadlock."
This is challenged on the basis that in actor-based languages, there simply are no locks to create such algorithms.
- mrkeen: "You wouldn't make that claim if your language didn't have locks."
Appreciation for Fray
Finally, some users expressed enthusiasm for the Fray tool itself.
- TYMorningCoffee: "Impressive! Can't wait to try Fray out at work."
- exabrial: "I wish I had this 20 years ago."