6 ms·
ConcurrentModificationException?
by dikaiosune 10y ago
ConcurrentModificationException?
- catnaroek 10y agoThat's hardly any better than undefined behavior. It's not the program you want to write, under any possible circumstance, and the language should tell you so.
- dikaiosune 10y agoPedantically, it's defined behavior, and doesn't use an interpreter lock. Granted, I'm completely head over heels for Rust, and I agree completely that ConcurrentModificationException is a crappy answer, but it is defined behavior (AFAIK).
- catnaroek 10y agoIt's true that throwing exceptions is defined behavior, but it's not defined in a way you'd actually want to use. For your actual purposes, it's undefined.
- lmm 10y agoIt's not defined. The library/VM is very good at throwing ConcurrentModificationException in practice, but it's specified as a best-effort thing, not to be relied upon.
- Athas 10y agoIt is significantly better than undefined behaviour, as it results in a noisy failure rather than silently incorrect results. Compile-time failures are best, sure, but I'll always take an exception over what is essentially data corruption.
- catnaroek 10y ago> It is significantly better than undefined behaviour, as it results in a noisy failure rather than silently incorrect results. This might be true in a deterministic setting, since the likelihood that a test suite will find the error is very high. But in a non-deterministic concurrent setting, throwing an exception that might be only caught once in a blue moon is just as bad as not doing anything about errors.
- dikaiosune 10y agoCorrupting data with no warning or visible signs is far, far worse than crashing the application.
- catnaroek 10y agoData corruption is possible even in memory-safe languages, anyway. For instance, invariants of data structures might be violated. If you're really serious about data integrity, ask yourself - does any language even attempt to describe data structures stored on disk?
- lmm 10y agoAn occasional exception and silent corruption the rest of the time is still a lot better than silent corruption all the time - it's much easier to notice in the first place, and as long as you have one instance of the exception you have a stack trace to start from. And in practice the JVM/standard library throws ConcurrentModificationExecption pretty reliably.
- catnaroek 10y ago> An occasional exception and silent corruption the rest of the time is still a lot better than silent corruption all the time The fundamental problem still remains, that in neither case can I use the language's semantics to guide the design of my program. > and as long as you have one instance of the exception you have a stack trace to start from Oh, really? How am I supposed to find what the problem is in the general case, from just a single exception stack trace that I might or might not get?
- SamReidHughes 10y agoI think a stack trace and an exception would help most people with a modicum of debugging skills.
- catnaroek 10y ago
- deleted 10y ago[deleted]
- aidenn0 10y ago??? Ask any C programmer if they could wave their magic wand and turn every single undefined behavior in their programs into a segfault how much better their life would be. It's not a small improvement it's a huge improvement.
- TickleSteve 10y agoThats simply not true. UB is simply the latest stick to hit C with. In day-to-day working nobody worries about UB at all as you generally don't notice it. Same with lack of a GC; this is a plus point for C for most applications, not a negative. (and yes, I do have plenty of experience in it, I've been using it for the past 20 years, have you?).
- catnaroek 10y ago> UB is simply the latest stick to hit C with. Honest question, which is the case? (0) You find it easy to determine, by visual inspection, whether a piece of code has undefined behavior. (1) Your coding practices make it difficult to accidentally introduce undefined behavior in the first place. > Same with lack of a GC; this is a plus point for C for most applications, not a negative. Agreed. C addresses use cases for which GC (or any other feature requiring heavy runtime support) is simply unacceptable.
- TickleSteve 10y agoIts a combination of both. The vast majority of all code you write will not invoke UB, most people tend to stick to an 'easy' subset of syntax, unlike say C++ where everyone uses a different subset of features making it in effect multiple languages. A combination of testing the known edge cases, wraparound issues, size issues, static analysis and tooling means running into an example of UB is extremely rare in most cases. It used to be that people used dynamic memory allocation to beat C with, but that is just a resource management issue. TBH, this is not rocket science. If you need dynamic memory allocation, you had damn well better know how to use it properly. Its an example of laziness and people ignoring the machine. Another example is performance; saying that a language comes within a factor of 2 of C's performance and therefore is fast is absolutely ridiculous. a factor of 2 is huge. You have to remember that people who write C are dealing with machine-specifics day-in, day-out. we're bit-fiddling and writing MPU code and drivers, etc. Basically, we're much more aware of the machine than higher-level softies, so what would normally be UB is actually DB in most cases, its defined by the compiler and hardware that we're intimately familiar with. ...and that isn't to say that you can't write high level abstracted code in C, the simplicity of the language lends itself to (properly) efficient implementation, not efficient in the sense of Java or Ruby ;o)
- dbaupp 10y agoJava's collections don't (and can't, without high cost) make any guarantees that they will throw such an exception whenever they are modified concurrently... for one, data races can have weird consequences that aren't easy to detect. On that point, data races in Java are not undefined behaviour, they just have very weak guarantees about what happens (basically isolated loads and stores do reasonable things, and no fancier operations are available) which is another alternative to the Rust approach and the GIL approach.
- catnaroek 10y ago> they just have very weak guarantees about what happens (...) which is another alternative Not a very usable one. It means that atomicity is something you have to fight very hard to actually get, and very easy to accidentally destroy.