Earlier quoted context omitted.
I couldn't give a better reply than this author: https://joeduffyblog.com/2010/01/03/a-brief-retrospective-on... Also, a phenomenal writing (as are his other posts) on the whole concurrency landscape, see: > A wondrous property of concurrent programming is the sheer number and diversity of programming models developed over the years. Actors, message-passing, data parallel, auto-vectorization, …; the titles roll off t…
I've read a few postmortems about STM. I have to take them with a grain of salt because I usually read those reports right after doing a bunch of STM programming, and right before doing a bunch more STM programming. Reports of its death have been greatly exaggerated. Here it is in 2006 featuring the same Tim from your article: https://www.youtube.com/watch?v=tve57vilywc I didn't start using it in anger till 2013-2014…
Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
31–40 of 54 posts
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#32Earlier quoted context omitted.
This is more of a toy example for how a set of atomic changes can still end up in an inconsistent state, e.g. setting January the 31st and February 3rd in quick succession from two or more different threads may result in Feb 31st being visible from a third thread. This is not solved by Rust and your struct will even get the Sync trait automatically, which may be not be applicable as in this case.
Given your example, I am convinced you've never written any Rust. Of course it does stop you doing shit like that. But in this example, even Java does it properly, since the constructor runs to completion before any Object is accessible to any Thread, not just the one creating it. You need to validate the state of the object in the constructor to prevent that, but TBH why are we talking about this, it's almost comple…
But what I'm quite obviously talking about is a Rust struct with 3 atomic fields. Just because I can safely race on any of its fields, doesn't mean that the whole struct can safely be shared, yet it will be inferred to be Sync.
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#33I wonder how this works when one runs test in parallel (something I always enable in any project). By this I mean configuring JUnit to run as many tests as cores are available to speed up the run of the whole test suite.
I took a peek at the code and I have the impression it doesn't work that well as it hooks into when a thread is started. Also, I'm not sure if this works with fibers.
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#34Earlier quoted context omitted.
Given your example, I am convinced you've never written any Rust. Of course it does stop you doing shit like that. But in this example, even Java does it properly, since the constructor runs to completion before any Object is accessible to any Thread, not just the one creating it. You need to validate the state of the object in the constructor to prevent that, but TBH why are we talking about this, it's almost comple…
Of course if you are creating a new object and you have an atomic handle to it, it is trivial to solve. Like, having immutable objects solves a lot of these problems. But what I'm quite obviously talking about is a Rust struct with 3 atomic fields. Just because I can safely race on any of its fields, doesn't mean that the whole struct can safely be shared, yet it will be inferred to be Sync.
We can see immediately that your type is broken because it allows us to directly set the date to February 31st, there's no concurrency bug needed, the type was always defective.
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#35Earlier quoted context omitted.
> the whole object may not make sense in certain states "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. C's stdlib provides a tm structure in which day of the week is stored in a signed 32-bit integer. You know, for when it's the negative two…
> “Make invalid states unrepresentable” I think this phrase sounds good but is not applicable to systems that touch messy reality. For example, I think it’s not even possible to apply it to the `tm` structure, as leap seconds are not known in advance.
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!
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#36Earlier quoted context omitted.
Of course if you are creating a new object and you have an atomic handle to it, it is trivial to solve. Like, having immutable objects solves a lot of these problems. But what I'm quite obviously talking about is a Rust struct with 3 atomic fields. Just because I can safely race on any of its fields, doesn't mean that the whole struct can safely be shared, yet it will be inferred to be Sync.
Object mutability isn't relevant here. A Date type which is mutable can ensure that all mutations are valid, it just can't do so while retaining this clumsy "LOL I'm just a D-M-Y tuple" API. We can see immediately that your type is broken because it allows us to directly set the date to February 31st, there's no concurrency bug needed, the type was always defective.
void setDate(int month, int day) {
if (notValidDate(month, date)) { throw; }
this.month = month; // atomic
this.day = day // atomic
}
Yet the whole function is not "atomic"/transactional/consistent, and two threads running simultaneously may surface the above error.Of course it can ensure that it is consistent, C code can also just ensure that it is memory safe. This is just not an inherent property, and in general you will mess it up.
The only difference is that we can reliably solve memory safety issues (GC, Rusty's ownership model), but we have absolutely no way to solve concurrency issues in any model. The only solution is.. having a single thread.
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#37[posted this in another thread, but maybe the author can clarify this] I wonder how this works when one runs test in parallel (something I always enable in any project). By this I mean configuring JUnit to run as many tests as cores are available to speed up the run of the whole test suite. I took a peek at the code and I have the impression it doesn't work that well as it hooks into when a thread is started. Also, I…
Fray currently does not support virtual threads. We do have an open issue tracking it, but it is low priority.
[1]: https://docs.gradle.org/current/userguide/java_testing.html#...
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#38Earlier quoted context omitted.
> “Make invalid states unrepresentable” I think this phrase sounds good but is not applicable to systems that touch messy reality. For example, I think it’s not even possible to apply it to the `tm` structure, as leap seconds are not known in advance.
I agree that messy reality can intervene, in the medium term (for about a decade) we'll need to handle leap seconds 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!
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#39Earlier quoted context omitted.
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) You make it sound like there is some modern development superseding what java has, but that's absolutely not the case. Like even rust is just pretty much a no-overhead `synchronized` on top of an object. It is necessary there, because data r…
> Like, actors can trivially deadlock/livelock, 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. This in particular is great: https://www.ponylang.io/discover/what-makes-pony-different/#... > Pony doesn’t have locks nor atomic operations or anything like that. Instead, the type system ensures at compile time that your concurrent program…
Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray
#40Earlier quoted context omitted.
Object mutability isn't relevant here. A Date type which is mutable can ensure that all mutations are valid, it just can't do so while retaining this clumsy "LOL I'm just a D-M-Y tuple" API. We can see immediately that your type is broken because it allows us to directly set the date to February 31st, there's no concurrency bug needed, the type was always defective.
void setDate(int month, int day) { if (notValidDate(month, date)) { throw; } this.month = month; // atomic this.day = day // atomic } Yet the whole function is not "atomic"/transactional/consistent, and two threads running simultaneously may surface the above error. Of course it can ensure that it is consistent, C code can also just ensure that it is memory safe. This is just not an inherent property, and in general…
In Rust this improved type doesn't have the defect, to call Rust's analogue of your setDate function you must have the exclusive mutable reference, which means there's no concurrency problem.
You have to do a whole lot of extra work to write the bug and why would you, just write what you meant and it behaves correctly.