Question

Assuming that I have the following code:

final Catalog catalog = createCatalog();

for (int i = 0; i< 100; i++{
    new Thread(new CatalogWorker(catalog)).start();
}

"Catalog" is an object structure, and the method createCatalog() and the "Catalog" object structure has not been written with concurrency in mind. There are several non-final, non-volatile references within the product catalog, there may even be mutable state (but that's going to have to be handled)

The way I understand the memory model, this code is not thread-safe. Is there any simple way to make it safe ? (The generalized version of this problem is really about single-threaded construction of shared structures that are created before the threads explode into action)

Was it helpful?

Solution

No, there's no simple way to make it safe. Concurrent use of mutable data types is always tricky. In some situations, making each operation on Catalog synchronized (preferably on a privately-held lock) may work, but usually you'll find that a thread actually wants to perform multiple operations without risking any other threads messing around with things.

Just synchronizing every access to variables should be enough to make the Java memory model problem less relevant - you would always see the most recent values, for example - but the bigger problem itself is still significant.

Any immutable state in Catalog should be fine already: there's a "happens-before" between the construction of the Catalog and the new thread being started. From section 17.4.5 of the spec:

A call to start() on a thread happens-before any actions in the started thread.

(And the construction finishing happens before the call to start(), so the construction happens before any actions in the started thread.)

OTHER TIPS

You need to synchronize every method that changes the state of Catalog to make it thread-safe.

public synchronized <return type> method(<parameter list>){
...
}

Assuming you handle the "non-final, non-volatile references [and] mutable state" (presumably by not actually mutating anything while these threads are running) then I believe this is thread-safe. From the JSR-133 FAQ:

When one action happens before another, the first is guaranteed to be ordered before and visible to the second. The rules of this ordering are as follows:

  • Each action in a thread happens before every action in that thread that comes later in the program's order.
  • An unlock on a monitor happens before every subsequent lock on that same monitor.
  • A write to a volatile field happens before every subsequent read of that same volatile.
  • A call to start() on a thread happens before any actions in the started thread.
  • All actions in a thread happen before any other thread successfully returns from a join() on that thread.

Since the threads are started after the call to createCatalog, the result of createCatalog should be visible to those threads without any problems. It's only changes to the Catalog objects that occur after start() is called on the thread that would cause trouble.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top