[concurrency-interest] reordering

Pete Soper Pete.Soper at Sun.COM
Fri May 19 10:39:49 EDT 2006


Bart Jacobs wrote:
> There are multiple ways to explain the Java memory model. One uses the 
> notion of "reorderings".
> 
> There is also a different explanation, which is not in terms of 
> "reorderings", and which may be clarifying for you. In this other 
> explanation, in each program execution, all actions performed by a given 
> thread occur in the order specified by the program (known as the program 
> order). The only difference with the single-threaded semantics is that, 
> for fields accessed concurrently by multiple threads, field reads do not 
> necessarily yield the value written by the most recent preceding write.
> 
> In short, the memory model has no effect on single-threaded programs, 
> and it affects only fields accessed concurrently by multiple threads.

But it's important to realize that "program order" is a certified Java 
tricky term, because modern compilers and modern hardware frequently 
make this order VERY different from the lexical order of the source code 
statements. I believe this is a major point Hans has been stressing.

A bit of history. Since the 80s compilers have been doing things that 
the average developer would flatly declare impossible, illegal, or at 
least cruel with respect to true understanding of what's happening at 
runtime. The situation gets worse with concurrency added to the picture. 
In the 80s there were two supercompiler camps developing concurrency 
detection to do automatic parallelization and to get the most out of 
programs making use of extended "parallel" version of languages like 
Fortran (before these features were standardized). But in both of those 
cases it fell on the compiler to avoid races and the worst that would 
happen to a developer was that his loops didn't run faster because he 
had a dependency that inhibited optimization and they ran partially or 
entirely as sequential code. By contrast, Java with the j.u.c. APIs is 
absolute freedom and absolute responsibility for the developer.

When David Holmes mentioned "program order" recently I found myself 
struggling to come up with a simple explanation for what this means in 
the context of the JMM with concurrent apps, to amplify this part of 
David's remarks. It needs to communicate the two dimensions of data 
dependencies on the one hand while not requiring a degree in 
supercompiler writing to be comprehensible on the other. The JLS 
definition of "program order" in chapter 17 says what needs to be said, 
but for a very limited readership!! But in my opinion the sooner folks 
get this "program order" term straight in their heads, the sooner they 
can climb higher up the JMM mountain.

David's key point recently was:

  "To create cross-thread happens-before relationships you have
to use synchronization tools, like Locks, sync regions, or volatiles."

But back to your statement. I don't agree. The memory model *does* have 
relevance to single threaded programs, as the "constructor completion 
happens-before finalizer runs" rule shows us. At least I hope it does! 
It would be terrible if the finalizer thread can say "well, we're tired 
of waiting: lets just run this thing anyway."  Put a different way, even 
if the developer thinks they have a 100% single-threaded application, 
it's not running in a single-threaded environment.

-Pete

> 
> Bart
> 
> Kazimierz Pogoda wrote:
> 
>> This "reordering" idea made me suspicious about my own code. I know this
>> is not directly connected with concurrent programming, but I want to ask
>> experts, if this code fragment works as it is expected to:
>>
>>
>> public void execute(final String sql) throws SQLException {
>>     final Connection conn = getConnection(); //throws SQLException
>>     boolean executed = false;
>>     try {
>>         execute(conn, sql); //throws SQLException
>>         executed = true;
>>     } finally {
>>         boolean commited = false;
>>         if (executed) {
>>             try {
>>                 conn.commit();
>>                 commited = true;
>>             } catch (SQLException e) {
>>                 log("cannot commit connection", e);
>>             }
>>         }
>>         if (!commited) {
>>             try {
>>                 conn.rollback();
>>             } catch (SQLException e) {
>>                 log("cannot rollback connection", e);
>>             }
>>         }
>>         try {
>>             conn.close();
>>         } catch (SQLException e) {
>>             log("cannot close connection", e);
>>         }
>>     }
>> }
>>
>> The intent of this code is to throw to caller the original SQLException
>> (thrown by execute(conn, sql) method), not SQLException indicating that
>> connection cannot be commited or closed. In case of any Throwable
>> (RuntimeException, Error) thrown in execute(conn, sql) method I expect
>> also an attempt to rollback the connection (If connection is taken from
>> the pool, other thread can commit it later).
>>
>> I'm using boolean flags "executed" to indicate if Throwable has been
>> throw, and boolean flag "commited" for SQLException on commit().
>>
>> Is it possible, that "reordering" will effect in unexpected state of
>> those flags after some thrown Throwable?
>>
>>   
> 
> 
> 
> Disclaimer: http://www.kuleuven.be/cwis/email_disclaimer.htm
> 
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
> 



More information about the Concurrency-interest mailing list