Re: Are there real use cases with the Java access modes?

Gregg Wonderly via Concurrency-interest <[email protected]> Mon, 19 Jul 2021 16:39:15 -0500
Newsgroups gmane.comp.java.jsr.166-concurrency
Message-ID <[email protected]>
Thanks for you comments.   I am still trying to assert that the problem is this kind of assumption about people writing the code, actually being trained software engineers.  Instead, think of them as self taught coders.  People who only every wrote “basic” or “vb” style integrations with just some knowledge that threads even exist, let alone, as in this case, knowing that the AWT event queue is involved and that there are threads (or more in the case of dialogs and other blocking actions) reaping events from the queue and dispatching them into your code.  Even the term callback or listener, for these people, doesn’t invoke any picture of “two” things working together.

I think my perspective may be something I assume everyone sees too.   In the 1990s, as Java rolled out and Mosaic “was” the web browser, we had “HTML authors” deployed en-masse to construct the web.  There were all the “software engineers” trying to solve the web server problems and create J2EE and lots of server side things by real software systems engineers.  Yet, 90% of people creating the web, were HTML authors, or later because Javascript codes (because Java was too big for the 32mb-128mb client/desktop PCs where applets where being attempted, but which couldn’t survive because they caused HUGE paging loads on under equipped PCs.   Later, these coders learned all kinds things like PHP, and 10’s if not 100’s of JavaScript platforms and libraries to do things on their HTML pages.

Then, there's the hobbiests that do technical things with small bits of software that they get from other people.  They try to “add” stuff, and “fix” stuff and contribute to all kinds of small communities of people using little Java desktop applications to facilitate portability to multiple computer platforms because many have PCs, some have Macs and some have Linux machines, and they want to all be able to do the same things, like use their home automation or other simple uProcessor control things etc.  These people have no idea how processors work in many cases.  They know nothing about caches, coherency, fences, etc.  Threads are something they’ve probably heard about, but they think of those as “server” things that make it possible to do a lot of things at once.   They are trying to create applications that don’t have “busy” things to do.  They write loops, like I did here, that just use timers, because some of them used to write MSDOS code with such timing loops for animations etc.  It’s this type of person that I am trying to highlight here.

I participate in several different technical communities like Amateur Radio where I’ve wanted to get the community to adopt Java as the preferred platform for lots of desktop application things.  I’ve written and shared lots of “jar-based” apps that would help people do interesting things in such communities.  But, the uptake has just been a huge hill, because Java is just too hard for them to comprehend all the details to get started.  There’s lots of details and things that I don’t really want to inject into this conversation.  But, I just want to point out that there are things like this particular issue, which “break” code by default.

Just 20mins ago I was having a discussion with a fairly new developer who had some questions about creating a “timing” class that would let him observe a count of operations over time, and then use the starting and ending time to show a “bandwidth” figure.  We talked about volatile and sharing related to the class fields and whether he should leave them non-volatile, use volatile or atomic references, synchronized methods etc.  And then he went right to another recent problem he had solved where this EXACT example had been encountered.  This was not in a desktop app but a Kafka based server app.  He had spent some period of time to workout that he need to make the boolean volatile to get the callback that changed the value of the boolean to be observed by the thread using the boolean for the loop control.

I still contend this is a surprise to many people.  They probably figure it out if they don’t have a choice to “move on” from solving the problem.  And once they figure out the volatile declaration, they have a keyword to look up and read about etc.  The default behavior of not having a designation for the default non-volatile “hoist” is really a problematic implicit behavior that is not the first thought process for many in my experience.  It’s the choice to “move on” that I feel drives people away from Java in some cases, because they really don’t now how to search for this problem because it’s by default.  There are lots of examples of “my loop doesn’t exit” for lots of other languages for countless reasons.  But not really anything on places like stackoverflow.com unless you know to include volatile and java.  Then you see this example:

https://stackoverflow.com/questions/55322624/why-is-this-code-not-going-into-an-infinite-loop-as-suggested-by-jsr133 <https://stackoverflow.com/questions/55322624/why-is-this-code-not-going-into-an-infinite-loop-as-suggested-by-jsr133>

which illustrates that the hoist starts happening if there are no call outs in the loop that the compiler can’t trace completely through, then the hoist doesn’t happen.  It’s this irregular behavior that just adds further to the frustration.

Gregg Wonderly

> On Jul 19, 2021, at 11:01 AM, Valentin Kovalenko via Concurrency-interest <[email protected]> wrote:
> 
> Hi Gregg,
> 
> > There is no explicit indication of Thread usage
> 
> There is only one explanation I can think of with regard to how the code in the listener added via `addActionListener` can be run: by a `java.lang.Thread` different from the one running `main` and blocked in `open` (this statement remains true even if one thinks about the project Loom). If an engineer writing the code like that does not even question himself about how can this application in principle be run in a single thread (that's the assumption in the example), then eliminating some optimizations that clearly do not violate JMM helps nothing. That same engineer can then pass between threads not a single `boolean`, but a more complex piece of data the same way with the same assumption (that there is only one thread), and be surprised to the same extent to observe not the piece of data that was shared. In fact, I think that the more often incorrectly synchronized code fails, the more likely it is that the author will discover and fix the bug, potentially improving his understanding along the way.
> 
> Regards,
> Valentin www.kovalenko.link <https://www.kovalenko.link/>
> 
> 
> Message: 4
> Date: Mon, 19 Jul 2021 09:17:05 -0500
> From: Gregg Wonderly <[email protected] <mailto:[email protected]>>
> To: Alex Otenko <[email protected] <mailto:[email protected]>>
> Cc: concurrency-interest <[email protected] <mailto:[email protected]>>
> Subject: Re: [concurrency-interest] Are there real use cases with the
>         Java access modes?
> Message-ID: <[email protected] <mailto:[email protected]>>
> Content-Type: text/plain; charset="utf-8"
> 
> Here’s what I’ve repeatedly shown in these conversations in the past.  There is no explicit indication of Thread usage.  This is just a plain and simple swing application that would be the kind of framework that the first Swing application would be written using.  But even some of the things I am doing here are a bit more than what I would expect to see in someones first swing app.
> 
> Gregg Wonderly
> 
> import java.awt.*;
> import java.awt.event.*;
> import javax.swing.*;
> import javax.swing.event.*;
> import java.util.logging.*;
> 
> public class Example2 extends JFrame {
> 
>         JTextField tm;
>         JButton btn;
>         boolean done;
>         public static void main( String args[] ) {
>                 new Example2(args).open();
>                 System.exit(0);
>         }
> 
>         public Example2(String args[] ) {
>                 JPanel p = new JPanel();
>                 p.setLayout( new FlowLayout() );
>                 p.add( btn = new JButton("Press to Exit") );
>                 p.add( tm = new JTextField(20) );
>                 this.add(p);
>                 btn.addActionListener( new ActionListener() {
>                         public void actionPerformed( ActionEvent ev ) {
>                                 Logger.getLogger(Example2.class.getName()).info("done...");
>                                 done = true;
>                         }
>                 });
>                 done = false;
>         }
> 
>         public void open() {
>                 pack();
>                 setLocationRelativeTo(null);
>                 setVisible(true);
> 
>                 // Does your JVM convert this statement to if( !done ) { while( true ){ ...  } }?
>                 while( !done ) {
>                         tm.setText(""+new java.util.Date() );
>                         try {
>                                 Thread.sleep(500);
>                         } catch( Exception ex ) {
>                                 Logger.getLogger(Example2.class.getName())
>                                         .log( Level.SEVERE, ex.getMessage(), ex );
>                         }
>                 }
>         }
> }
> 
> _______________________________________________
> 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