My (lack of )wisdom about threads

S

Stefan Ram

So, inspired by »Swing application architecture question.«, here is
my (lack of )wisdoms about threads:

- To correctly use multi-threading, a special education is needed.
I do not yet have taken the time to undergo this, so I need
to refrain from using threads (that is, more than one thread).

- However, Java might force me to use threads, e.g., when using
Swing. So I /will/ use multi-threading when being forced to,
but take care only to use code patterns from common Swing
examples and not do own inventions in this realm.

Recently, I read something I liked very much. So, whenever I
would start to do own inventions in multi-threading, my first
step would be to follow this advice:

»As much as possible, prefer to keep each thread's data
isolated (unshared), and let threads instead communicate
via asynchronous messages that pass copies of data.«

http://www.ddj.com/go-parallel/article/showArticle.jhtml?articleID=215900465

Does anyone else like this advice?

So, when I should ever start to use threads in Java beyond
what I am forced to do, I'd implement a message-passing
framework/library/pattern for my threads first.

I do not know if this remark would be helpful for the »Swing
application architecture question.«, but since I am aware that
I do not yet know enough about threads in Java to give any
advice to anyone else, I did not dare to post into that thread
[no pun intended].

But I wonder whether a communication between a view and a
model that live in different threads can also be made robust
by basing this communication on such messages.
 
M

Mark Space

Stefan said:
Does anyone else like this advice?

Sometimes, but it's usefulness is limited. It's like saying "As much as
possible, try to use local variables because they have the most limited
scope." By itself, that statement won't allow you to design correct
programs. There's much more to programming than just variable scope.
So, when I should ever start to use threads in Java beyond
what I am forced to do, I'd implement a message-passing
framework/library/pattern for my threads first.

The solution here is simple: you must buy and read Java Concurrency in
Practice.

<http://jcip.net/>

There's just no way you can be a Java programmer today and not know how
to deal with threads. Threads are not hard, but I didn't understand
them either until I read the first chapter of that book. Then it all
cleared up.

This is not rocket science. Threads seem mysterious and hard until you
have the full explanation, then it all makes sense. If you can
understand basic algorithms -- for example, if you can write a basic
tree traversal -- then you have the smarts to understand threads. Don't
procrastinate any longer. Buy the book, read the first chapter, get
started now.
 
J

Joshua Cranmer

Stefan said:
So, inspired by »Swing application architecture question.«, here is
my (lack of )wisdoms about threads:

- To correctly use multi-threading, a special education is needed.
I do not yet have taken the time to undergo this, so I need
to refrain from using threads (that is, more than one thread).

I wouldn't say that special education is needed at Java's level of
abstraction. I've been able to do it to some degree, and I certainly
never had it yet. If you know what synchronized does and when you might
want to use volatile, you'll probably be fine. Java 5 and 6 (and
possibly 7) introduce new concurrency utilities that eases some use,
especially if you have a lot of threads interacting.
Recently, I read something I liked very much. So, whenever I
would start to do own inventions in multi-threading, my first
step would be to follow this advice:

»As much as possible, prefer to keep each thread's data
isolated (unshared), and let threads instead communicate
via asynchronous messages that pass copies of data.«

http://www.ddj.com/go-parallel/article/showArticle.jhtml?articleID=215900465

Does anyone else like this advice?
Yes.

But I wonder whether a communication between a view and a
model that live in different threads can also be made robust
by basing this communication on such messages.

Another way of looking it is that such communication would form an event
system.
 
L

Lew

Peter said:
Threads aren't so bad, especially if you avoid trying to be clever. Try
to keep processing within a thread and independent from other threads as
much as possible, and when the threads do need to interact, use existing
mechanisms for doing so: "volatile", "synchronized", and the various
concurrency objects Java provides if you need for threads to coordinate
their execution status with each other.
...
Note that for the most typical, simple uses of threads in a Swing
application, the SwingWorker abstracts most if not all of the basic
issues that come up, allowing you to focus on getting your code right
and not worrying too much about the actual threading. You'll still run
into synchronization issues if _during_ the thread processing there has
to be interaction, other than property changes already supported
directly by SwingWorker (e.g. the "progress" property). But in the
typical cases, this doesn't come up. ....
try to design and use immutable data structures. They have
advantages even outside of threading, but they make certain threading
issues much simpler to implement and reason about. ....
And in certain other
cases, it would suffice to use a "volatile" variable to refer to the
immutable instance, instead of having to lock with the "synchronized".

None of this is quite as cut-and-dried as the above might seem to
suggest, but immutable data structures lend themselves very well to the
kind of message-passing that the advice you found is talking about,
because you don't actually need to make copies of the data (the instance
won't change, so you can safely always use the original instance).

Another valuable point: if one does share mutable data between threads, then
it is important that all accesses to that mutable data, both read and write,
be protected by some form of synchronization, whether 'volatile' or
'synchronized' or some other way. (Naturally all these accesses have to use
the same way - it is a classic bug to attempt synchronization to the same data
on different locks or monitors.) This is because the memory model only
guarantees communication of changes between threads across specific
synchronization boundaries.

Also, synchronization needs to be transactional - that is to say, if multiple
items or methods contribute to some synchronous state then they all have to be
part of the same critical section. For example, to update a shared mutable
two-dimensional coordinate (x, y), it is insufficient to separately
synchronize the accesses to 'x' and 'y', or to make them independently
volatile variables. Thus:

public class Foo
{
private volatile int x;
private volatile int y;
...
}

will not guarantee that x and y are consistent with each other across threads,
nor will

public synchronized void setX( int nX ) { x = nX; }
public synchronized void setY( int nY ) { y = nY; }

You would need something like

public synchronized void updateCoord( int nX, int nY )
{
x = nX;
y = nY;
}

Of course, you'd have to synchronize the getter with the same monitor as used
by 'updateCoord()' in this example.
 
R

Roedy Green

- To correctly use multi-threading, a special education is needed.
I do not yet have taken the time to undergo this, so I need
to refrain from using threads (that is, more than one thread).

IF you can arrange that threads don't modify the same variables, just
look at the same final variables, there is nothing to threads. You
don't need any synchronization. Local variables are private to each
thread so they are not a problem.


See http://mindprod.com/jgloss/thread.html
and follow the links.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"If people become accustomed to lying, they will unconsciously commit every possible wrong deed. Before they can act wickedly, they must lie, and once they begin to lie they will act wickedly without concern."
~ Gautama Buddha
 
T

Tom Anderson

I wouldn't say that special education is needed at Java's level of
abstraction. I've been able to do it to some degree, and I certainly never
had it yet. If you know what synchronized does and when you might want to use
volatile, you'll probably be fine. Java 5 and 6 (and possibly 7) introduce
new concurrency utilities that eases some use, especially if you have a lot
of threads interacting.

Some of them also make life more complicated, because you have more
options!

I do like AtomicBoolean, though. It lets you implement something that's
like an optional synchronized block. Rather than:

private final Object lock = new Object();

synchronized (lock) {
doStuff();
}

You do:

private final AtomicBoolean lock = new AtomicBoolean();

if (lock.compareAndSet(false, true)) {
try {
doStuff();
}
finally {
lock.set(false);
}
}

This still guarantees mutual exclusion, but means that if a second thread
comes along while a first thread is in the critical section, rather than
blocking, it skips over the critical section. I used this construct to
guard some housekeeping work in a multithreaded program; something that
needs to be done quite often, but must only be done by one thread.

tom
 
R

Roedy Green

Does anyone else like this advice?

So, when I should ever start to use threads in Java beyond
what I am forced to do, I'd implement a message-passing
framework/library/pattern for my threads first.

Instead, look for library code written by the experts. You leave the
tricky synchronisation code up to them. Get a copy Java Concurrency
in Practice to guide you through the new multithread API.

http://www.amazon.com/gp/product/03...mp=1789&creative=9325&creativeASIN=0321349601

Only for very simple problems or as a last resort when you can't find
library code should you resort to writing you own code that uses low
level tools like synchronized and wait.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"If people become accustomed to lying, they will unconsciously commit every possible wrong deed. Before they can act wickedly, they must lie, and once they begin to lie they will act wickedly without concern."
~ Gautama Buddha
 
A

Arne Vajhøj

Tom said:
Some of them also make life more complicated, because you have more
options!

I do like AtomicBoolean, though. It lets you implement something that's
like an optional synchronized block. Rather than:

private final Object lock = new Object();

synchronized (lock) {
doStuff();
}

You do:

private final AtomicBoolean lock = new AtomicBoolean();

if (lock.compareAndSet(false, true)) {
try {
doStuff();
}
finally {
lock.set(false);
}
}

This still guarantees mutual exclusion, but means that if a second
thread comes along while a first thread is in the critical section,
rather than blocking, it skips over the critical section. I used this
construct to guard some housekeeping work in a multithreaded program;
something that needs to be done quite often, but must only be done by
one thread.

You could also use Semaphore.tryAcquire for a similar effect.

java.util.concurrent is a great package.

I assume that one could code the exact same thing oneself, but
it is always nice to get high quality code for free.

Arne
 
A

Arne Vajhøj

Roedy said:
IF you can arrange that threads don't modify the same variables, just
look at the same final variables, there is nothing to threads.

Not true.

There can still be both visibility and atomicity problems.

Arne
 
M

Mark Space

Arne said:
Not true.

There can still be both visibility and atomicity problems.

No, I think Roedy is correct. *Final* variables are treated specially
by the JVM, and are thread safe.
 
L

Lew

Mark said:
No, I think Roedy is correct. *Final* variables are treated specially
by the JVM, and are thread safe.

Not always. Final variables can point to mutable objects. Such accesses must
be synchronized to be thread safe.

Final variables that point to immutable objects or constants are thread safe.
 
T

Tom Anderson

Not always. Final variables can point to mutable objects. Such accesses
must be synchronized to be thread safe.

Access to the final variables don't need to be - access to the non-final
variables in the referents do. But what Roedy said was "IF you can arrange
that threads don't modify the same variables, just look at the same final
variables", so if you're following his advice, there won't be any
non-final variables. So he *is* right. It's worth clarifying that his
advice means not using any non-final variables even in referred-to
objects, but if that's what you were saying, then it would be worth
clarifying that you were making a clarification!

tom
 
T

Tom Anderson

You could also use Semaphore.tryAcquire for a similar effect.

Aargh! Too many choices!
java.util.concurrent is a great package.

I assume that one could code the exact same thing oneself, but it is
always nice to get high quality code for free.

The atomic classes use special machine-code instructions (the sublime
ldarx/stwcx on PowerPC, the brutish lock cmpxchg on x86, etc), which you
wouldn't otherwise be able to write in java (without JNI, at least). You
could build classes with the same semantics using synchronized, but i
wouldn't say you could code the exact same thing oneself.

Apart from the atomics, though, i *think* all the stuff in
java.util.concurrent could be written in java by ordinary programmers, as
you say.

tom
 
L

Lew

Tom said:
Access to the final variables don't need to be - access to the non-final
variables in the referents do.

This is a clarification of what I said. Thank you.
... It's worth clarifying that
his advice means not using any non-final variables even in referred-to
objects, but if that's what you were saying, then it would be worth
clarifying that you were making a clarification!

As you just did.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top