Concurrency?

K

Knute Johnson

I have a List that I need to access in two threads, in one thread I
clear, add and get the size of the List. The other just iterates over
the List. To prevent a ConcurrentModificationException, I can't allow
the list to be cleared or elements added when it is being iterated in
the other thread. My question is, will there be any problem using the
size() method unsynchronized in the thread that clears and adds
elements? Visibility shouldn't be a problem because all the changes to
the List occur in that thread.

Thanks,
 
J

Joshua Cranmer

Knute said:
I have a List that I need to access in two threads, in one thread I
clear, add and get the size of the List. The other just iterates over
the List. To prevent a ConcurrentModificationException, I can't allow
the list to be cleared or elements added when it is being iterated in
the other thread. My question is, will there be any problem using the
size() method unsynchronized in the thread that clears and adds
elements? Visibility shouldn't be a problem because all the changes to
the List occur in that thread.

ConcurrentModificationException arises from use of iterators, not
multiple threads (although multithreading is probably a common way that
it gets thrown).

The size() method is read-only, and therefore safe from concurrent
modifications modulo cross-thread synchronization. Since it seems you're
using it on the only modifying thread, that shouldn't be a problem.
 
K

Knute Johnson

Joshua said:
ConcurrentModificationException arises from use of iterators, not
multiple threads (although multithreading is probably a common way that
it gets thrown).

The size() method is read-only, and therefore safe from concurrent
modifications modulo cross-thread synchronization. Since it seems you're
using it on the only modifying thread, that shouldn't be a problem.

Thanks Joshua.
 
M

Mark Space

Knute said:
I have a List that I need to access in two threads, in one thread I
clear, add and get the size of the List. The other just iterates over
the List. To prevent a ConcurrentModificationException, I can't allow
the list to be cleared or elements added when it is being iterated in
the other thread. My question is, will there be any problem using the
size() method unsynchronized in the thread that clears and adds
elements? Visibility shouldn't be a problem because all the changes to
the List occur in that thread.

What do you mean "unsynchronized"? Is the List synchronized or do you
always synchronize on some common lock?

Read-only or not, visibility is always an issue unless the backing
variables are declared "volatile". Unless you are certain that you are
already synchronizing correctly, I think I'd just go ahead and make the
List into the synchronized version. You'll still need to lock the whole
thing for iterating over though, or you'll get concurrent modification
exceptions.
 
L

Lew

However, if the collection changes size in one thread and the size() method in
another thread doesn't have a /happens-after/ relationship to the change, it
might not see the change.
 
D

Daniel Pitts

Mark said:
What do you mean "unsynchronized"? Is the List synchronized or do you
always synchronize on some common lock?

Read-only or not, visibility is always an issue unless the backing
variables are declared "volatile". Unless you are certain that you are
already synchronizing correctly, I think I'd just go ahead and make the
List into the synchronized version. You'll still need to lock the whole
thing for iterating over though, or you'll get concurrent modification
exceptions.
I think the OP was saying that the size() method would only be called
from the thread that did any mutating of the data structure. In which
case, the happens-before relationship of a single thread will enforce a
correct result. Ofcourse, if it isn't a standard list, and iterating
actually changes the structure, all bets are off.

To the OP: Can you give more details about the two threads? Does the
thread which modifies the list only do it infrequently, and the other
one inspect the list frequently? Visa versa? Something else?

If the list is updated infrequently, you might be better off having a
volatile reference to a list, and have the "writing" thread re-create a
new (unmodifiable) list with the new data, and place it into that
volatile reference. In the reading thread, list.iterator() will return
the iterator of the "most recently set" list, and iterate through that
until completed, regardless of new lists that come and go.
 
K

Knute Johnson

Mark said:
What do you mean "unsynchronized"? Is the List synchronized or do you
always synchronize on some common lock?

What I was trying to say was that if the add() and clear() were
synchronized and the size() wasn't, would there be a visibility problem
in that thread with the size() method.
Read-only or not, visibility is always an issue unless the backing
variables are declared "volatile". Unless you are certain that you are
already synchronizing correctly, I think I'd just go ahead and make the
List into the synchronized version. You'll still need to lock the whole
thing for iterating over though, or you'll get concurrent modification
exceptions.

You have no control over the reference array in a List and can't make it
volatile. If you mean the reference to the list, final works just as
well. Synchronizing access will obviate any requirement to wrap it in
Collections.synchronizedList and is necessary to protect the iteration.

In the end I used a CopyOnWriteArrayList as it solves all the problems
with the least hassle.

Thanks,
 
K

Knute Johnson

Lew said:
However, if the collection changes size in one thread and the size()
method in another thread doesn't have a /happens-after/ relationship to
the change, it might not see the change.

Thanks everybody for the responses.
 
K

Knute Johnson

Daniel said:
I think the OP was saying that the size() method would only be called
from the thread that did any mutating of the data structure. In which
case, the happens-before relationship of a single thread will enforce a
correct result. Ofcourse, if it isn't a standard list, and iterating
actually changes the structure, all bets are off.

To the OP: Can you give more details about the two threads? Does the
thread which modifies the list only do it infrequently, and the other
one inspect the list frequently? Visa versa? Something else?

Hard to quantify infrequently but the two threads could act upon the
List simultaneously so they must be protected. The thread that iterates
over the list does not modify the list.
If the list is updated infrequently, you might be better off having a
volatile reference to a list, and have the "writing" thread re-create a
new (unmodifiable) list with the new data, and place it into that
volatile reference. In the reading thread, list.iterator() will return
the iterator of the "most recently set" list, and iterate through that
until completed, regardless of new lists that come and go.

I ended up using a CopyOnWriteArrayList that creates a separate array
for the iterator. It accomplishes pretty much what you describe.

Thanks,
 
T

Tom Anderson

I have a List that I need to access in two threads, in one thread I
clear, add and get the size of the List. The other just iterates over
the List. To prevent a ConcurrentModificationException, I can't allow
the list to be cleared or elements added when it is being iterated in
the other thread. My question is, will there be any problem using the
size() method unsynchronized in the thread that clears and adds
elements? Visibility shouldn't be a problem because all the changes to
the List occur in that thread.

Should be fine, i reckon.

tom
 
T

Tom Anderson

What I was trying to say was that if the add() and clear() were synchronized
and the size() wasn't, would there be a visibility problem in that thread
with the size() method.

There won't. Actions within a single thread always happen in the right
order.

tom
 
M

Mark Space

Knute said:
What I was trying to say was that if the add() and clear() were
synchronized and the size() wasn't, would there be a visibility problem
in that thread with the size() method.


Well, I think Arne is right, in one thread, no problem. I'm with Zig
however: sometimes-synchronized objects are code-smell. I can't
pin-point it, but I'm sure there's unanticipated ways of messing this up
when multiple threads are involved.

You have no control over the reference array in a List and can't make it
volatile. If you mean the reference to the list, final works just as
well. Synchronizing access will obviate any requirement to wrap it in
Collections.synchronizedList and is necessary to protect the iteration.


Well, you can derive your own concrete List and use that. Just saying.

In the end I used a CopyOnWriteArrayList as it solves all the problems
with the least hassle.


This sounds like a 100% excellent solution. I can't see anything wrong
with this at all.
 

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

Forum statistics

Threads
473,780
Messages
2,569,610
Members
45,254
Latest member
Top Crypto TwitterChannel

Latest Threads

Top