Re: Swing/AWT concurrency
Olivier Peyrusse via Concurrency-interest <[email protected]> Thu, 22 Jul 2021 07:38:08 +0000
| Newsgroups | gmane.comp.java.jsr.166-concurrency |
|---|---|
| Message-ID | <VHn89d8iCIt0IoWO6N50HtbKqktsmTD75-8iI3OLbYc1jnRks5n7A8Q96FiWXpg1JagolpR7Omu70E00o2HCrFyn6WnfxVsShzoLtsojd8M=@protonmail.com> |
If I may chime in, even if I am not a Swing developer, I find the policy of "final or volatile" a bit strange. It gives a false sense of security as it seems that the only way volatile really help is for boolean, while a standard `this.i += 1` will often fail. I may be inspired / tainted by functional languages where immutability is everywhere, but I would have stick to a rule like "final primitive fields or final Atomic classes". This way, you must explicitly deal with updates, not to painfully using the series of updateAndGet. And it seems to be suggested in your linked document, though solutions with volatile are present a lot. I would have thought that one starts using volatile when they see performance issue with "safer" methods. But it this moment, one stops being a beginner and dives into Java concurrency :) Have a nice day Olivier Peyrusse ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ Le mercredi 21 juillet 2021 à 11:14 AM, Gregg Wonderly via Concurrency-interest <[email protected]> a écrit : > At various times over the years, I’ve met people who have talked about this issue and their own practical problems around non-volatile being the default. In several cases, they have told me that they’ve just adopted the practice that in any class they create (even outside of Swing use), class level declarations should either by final, or volatile. The final fields are objects that manage concurrency themselves, or are primitive types that are parameters to constructors or are otherwise immutable. The other fields are declared volatile because then if the user of the class uses it in more than one thread, the values of such fields will readily escape hoisted references or writes to those fields will not be missed by subsequent reads. In many cases, this can result in data races, but for things that are atomically assigned or referenced values, this at least keeps sanity in the usage, and for non-atomic assignment/reference, one can observe the value changing erratically at least to then have a problem to solve that generally will require Atomic<T> to be used. > > This document, https://apps.dtic.mil/sti/pdfs/ADA528370.pdf, describes all of the details around the fragility of non-volatile values in various ways and usages. I think everyone here would agree with the observations there and the examples readily describe the pitfalls of non-volatile values. These scenarios illustrate examples of non-volatile use including the text around section 2.1.1, which is the structure that I’ve illustrated and discussed here. It’s a specific example that it well recognized and documented. > > Gregg Wonderly > >> On Jul 20, 2021, at 6:18 PM, Brian S O'Neill via Concurrency-interest <[email protected]> wrote: >> >> I was able to reproduce the problem by changing the example code to have an empty loop body. It now looks like this: >> >> while (!done) {} >> tm.setText("" + new java.util.Date()); >> >> A new user might not understand the benefit of adding the sleep in the loop, but adding that back in does prevent hoisting. >> >> I don't think the problem is totally made up. I've worked with new and experienced programmers who make mistakes like this, and it's not at all obvious why this is a problem. >> >> On 2021-07-20 02:38 PM, Alex Otenko wrote: >> >>> I think the problem is totally made up. You can't be using Swing, and not know about threads. Thread safety clauses are all over documentation for components. The hoist that Gregg has an issue with can happen only if non-thread-safe methods are used. Other methods are likely using locks inside, so even though not synchronized properly, the hoisting in question simply cannot happen. >>> I was hoping to see a working example that shows otherwise. >>> Alex >>> On Tue, 20 Jul 2021, 21:47 Brian S O'Neill via Concurrency-interest, <[email protected]<mailto:[email protected]>> wrote: >>> This is a continuation of the "Are there real use cases with the Java >>> access modes?", but in a separate discussion thread to maintain >>> focus on >>> what I feel is the crux of the matter. >>> Gregg pointed out a potential problem that can affect new Java users >>> when writing desktop applications. In particular, one thread can set a >>> shared "isDone" field, and another thread might never observe this. In >>> practice, the specific example which was provided wouldn't actually >>> have >>> a problem, but knowing why this is the case isn't something that a new >>> Java user would have any knowledge of. In other languages/frameworks, >>> users don't need to understand concurrency except as an advanced topic. >>> The suggested solution is to require that all fields be volatile as >>> default. This naturally causes a knee-jerk reaction to anyone who wants >>> the Java platform to be concurrent and highly efficient. And for those >>> of us who mostly write server-side applications, we don't understand >>> why >>> this change is needed at all. After all, there's a bunch of modern >>> async/task scheduling frameworks available that allow new users to >>> write >>> safe, efficient, and completely non-surprising programs. >>> New users of Swing/AWT don't have this luxury. And to them, Java == >>> Swing, and so any problems in Swing are equivalent to problems in Java >>> itself. >>> Would declaring all fields as volatile actually fix Swing? Not really. >>> Consider the case in which one thread does this: >>> isDone = true; >>> doneMessage = "all done!"; >>> Both fields are volatile, and both are thus visible to other threads. >>> Except what I did is wrong, and it's not obvious to a new user. In >>> their >>> head, they think, "this task is done, and the message is 'all >>> done'". So >>> naturally the code should be written the same way. In almost all cases, >>> this works just fine. Randomly it fails, and now you have to explain to >>> the new user the concepts of concurrency, sequential consistency, etc. >>> If Swing/AWT was designed around a "pure" event loop, then all tasks >>> run >>> atomically, and so the order in which fields are assigned isn't >>> relevant. They don't need to be volatile either. If the event loop >>> implementation wants to use multiple threads, then it's responsible for >>> using the correct thread-safe constructs and memory barriers to prevent >>> strange issues from cropping up. >>> Modern frameworks exist on the server side to do just this, but have >>> they been adapted for writing desktop apps? Is there an alternative to >>> Swing/AWT? If not, my hope is that someone reading this becomes >>> inspired >>> to write such a thing. In the past, this seemed quite scary because it >>> would likely involve a bunch of JNI coding. Hopefully the Panama >>> project >>> will take the sting out of this. >>> By the way, I know very little about "real world" Swing >>> applications. My >>> understanding of the issues might be wrong, so please be nice! >>> _______________________________________________ >>> Concurrency-interest mailing list >>> [email protected] >>> <mailto:[email protected]> >>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest >>> <http://cs.oswego.edu/mailman/listinfo/concurrency-interest> >> >> _______________________________________________ >> Concurrency-interest mailing list >> [email protected] >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest _______________________________________________ Concurrency-interest mailing list [email protected] http://cs.oswego.edu/mailman/listinfo/concurrency-interest