How can any single-threaded program be a valid multi-threaded program?

I read the book "Java Concurrency In Practice". In the second chapter I read the statement

any single-threaded program is also a valid multi-threaded program

I could not understand this statement.

Please share your thoughts with this so that my confusion can be cleared. Thanks in advance.

+5
source share
3 answers

Please note that the operator does not imply that any correct single-threaded program is also a correct multi-threaded program, the author simply states that it is possible to convert any one threaded program that will be executed in a multi-threaded environment.

However, if the program is no longer correct in a single-threaded environment, then it cannot be correct in a more complex multi-threaded environment.

From book:

Since any single-threaded program is also a valid multi-threaded program, it cannot be thread-safe if it is not even correct in a single-threaded environment.

If the object is correctly implemented, the sequence of operations calls to public methods, as well as reading or publishing public fields, violate any of its invariants or message conditions. No set of operations performed sequentially or simultaneously on thread safe class instances can cause the instance to be in an invalid state.

And this:

If the free use of "correctness" bothers you here, you might prefer to think of a thread-safe class that is no more broken in a parallel environment than in a single-thread environment.

@yshavit Before you start thinking about multi-threaded correctness, make sure you have at least one threaded correctness.

+3
source

any single-threaded program is also a valid multi-threaded program

Basically, this means that any single-threaded program can be used in a multi-threaded context. Take the following code, for example:

class A { public void doSomething() { } } 

If we look at the above class separately, it is certainly a single-threaded program; however, the same program can be used in a multi-threaded context:

 Thread thread1 = new Thread(new Runnable() { public void run() { A a = new A(); a.doSomething(); } }).start(); Thread thread2 = new Thread(new Runnable() { public void run() { A a = new A(); a.doSomething(); } }).start(); 

Speaking of a specific related paragraph in a book that you didn't ask about, but worth discussing:

No operations performed sequentially or at the same time instances of the thread-safe class can cause the instance to be in an invalid state

Let's say some state in our class:

 class A { int iCantBeNegative = 10; public void doSomething() { --icantBeNegative; } } 

The programmer's expectation was that iCantBeNegative should never be less than zero, and yet they did nothing to meet this requirement. Since this program is primarily incorrect in a single-threaded context in terms of expectations ( iCantBeNegatvie will be <0 if doSomething is called 11 times or more per line), this is most definitely wrong in a multi-threaded context.

+2
source

"any single-threaded program is also a valid multi-threaded program"

Without going to the book or reading the section, there are many ways for a single-threaded application to be multi-threaded when working in the JVM. There are several specific JVM threads that deploy when the JVM starts. They include gc threads, finalizer, JMX threads (if included) and others. These threads run in the background to help the JVM work efficiently.

For example, in my OSX block, the following threads are deployed by default:

  • Main
  • Link handler
  • Finalizer
  • Signal Manager
  • Attach Listener
  • A series of RMI and JMX threads if JMX is enabled

In addition, since the main thread executing the user application code encounters synchronized , blocks, or accesses volatile fields in libraries or JDKs, then the main thread goes through memory barriers, captures and releases locks, etc., as a multi-threaded application. This may be a link to the author.

Finally, it is important to understand that the term "reentrant" was created before the concept of flows was even invented. The code must be properly written in order to be reentrant due to recursive methods or interrupt handlers, which meant that the code could be entered twice, even if it wasn’t for several "threads". This is necessary to write the correct reentrant code, it was necessary before switching the context, exchanging I / O, cache, etc. Yes, I show my age here.

+1
source

Source: https://habr.com/ru/post/1265188/


All Articles