Threads question... (newbie)

  • Thread starter Agustin Chernitsky
  • Start date
A

Agustin Chernitsky

Hi guys. I have one very very big doubt on java threads.

Let's say I have a collection Array with lots of objects inside. These
objects inside must be accessed by n number of threads. Now, to get some
syncronization on the data (each object inside the collection holds
references to other obj), I have to make the following methods on the
collection Array Synchronized:

addObject
removeObject

So... when one thread is using addObject, no other thread can access the
collection obj. First doubt: is this ok?

now, lets say I want to read or retrieve some info from the obj inside the
collection array. I will use the following method:

getObject

Here is my biggest doubt:

Case 1: If I make the getObject method Syncronized, I will form a queue of
threads when each threads wants to read from the collection. In my
application, this will happen a lot (most of the time really). I will kill
the performance of my application if this is the case...

Case 2: If I don't synchronize the getObject method, what will happen?

A1: All threads will be able to read from the collection unless the
addObject or removeObjects are locking the collection?
A2: All threads will be able to read from the collection even if the
addObject or removeObjects are locking the collection? (I don't like this
one...)

Well... hope someone can clear this for me... Thanks so much!

Agus.
 
A

Agustin Chernitsky

Hi Sunitha,

Thanks for the reply... I made comments below.

Sunitha Kumar said:
Yes, you want to "lock" access to the object, so no other thread can access
it, while it is being modified. The usual analogy is to a restroom - when a
thread enters a synchronized method, it shuts the door and locks it. When
another thread tries to access the synchronized method, it can't open the
door, so it stops running. Eventually, the first thread exits its
synchronozed methos and unlocks the door. (You have to make your addObject
and getObject method synchronized for this to work.)

Good... I was on the right path then...
Not necessarily. Consider this approach: while some condition is true (say,
the condition for the thread not to access the collection, for example the
Collection is empty, etc.) call the wait method for the thread. Once the
condition is no longer true, then do your modification and then call the
notifyAll() which "wakes" all the threads waiting to access the collection
and the process continues.

Yes, but imagine the collection is full... with 100 objects. And you have 20
threads accessing the collection every 2-5 seconds, at the same time...
won't this cause a perfomance problem if only one thread per time can read
the collection?
Hmm, bad things. For one, all your threads will be clamoring to get to your
collection and two, your program might never terminate. The rule is, if an
object is being shared among many threads, then you want to make the methods
that modify the object, synchronized.

Do you consider read info from an object the same as modify? If the object
is locked by a addObject or removeObject, will a getObject method call be
blocked as well?

Yes, I read that... it's quite good.. still, I needed to ask :)
Hope this helps.

You helped a lot!
 
A

Adam Maass

Agustin Chernitsky said:
Yes, but imagine the collection is full... with 100 objects. And you have 20
threads accessing the collection every 2-5 seconds, at the same time...
won't this cause a perfomance problem if only one thread per time can read
the collection?

Maybe. But in general, you need to synchronize both read and write access.

It'll take a lot more concurrency than 20 threads, each accessing every
2-to-5 seconds, for lock contention to start becoming noticeable. But you
still want to design so that each thread holds the lock for the minimum
possible time. That is, you want to synchronize the read for *just long
enough* to pull an object reference out of the array. You release the lock
before doing anything else with that reference.

-- Adam Maass
 
S

Steve Horsley

Yes, but imagine the collection is full... with 100 objects. And you
have 20 threads accessing the collection every 2-5 seconds, at the same
time... won't this cause a perfomance problem if only one thread per
time can read the collection?

You need to bear in mind the _depth_ at which you are synchronizing. For
example, java.util.Vector is a synchronized collection and _might_ do what
you want, but remember that you are only synchronizing while you are in
the get(int index) method. This is over in microseconds. Now you have your
reference to an Object in the Vector, and are free to use the reference to
access the Object BUT such access is not synchronized! This could be good
or bad, depending on your code. Good because your object manipulation can
happen in multithreaded parallel heaven, bad because you _might_ still
need to worry about concurrent access/modification of the Objects
contained in the Vector.

Actually, unless you are on a multi-processor machine, synchronizing all
access to the entire data structure won't slow things down (unless you
perform blocking I/O inside the synchronized code). As long as the CPU is
kept busy then it can do no better, regardless whether it takes one thread
at a time to completion or swaps between several concurrent threads.
Repeated acquiring and releasing of a lock is only a small load, and is
nothing compared to the requirement for correct program function.

methods that modify the object, synchronized.

Do you consider read info from an object the same as modify? If the
object is locked by a addObject or removeObject, will a getObject method
call be blocked as well?

Again, don't confuse synchronized access to a Collection with any
subsequent access to the retrieved Objects. With Vector, all accesses (add
delete, get) are synchronized. This is as it should be, to prevent get()
from misreading a partially modified structure.

The same should be true for any object which may be accessed my multiple
threads. Unless you are _very_ sure that you want otherwise, you should
use private variables and synchronized accessor / modifier methods. This
will protect you from concurrent access, and from memory caching problems
on multiprocessor systems.

So:

1) Definitely use synchronized accesses to your Collection - a Vector
might be a good choice.

2) Also synchronize all the contents objects unless your are absolutely
certain that two threads will never try to retrieve and access the same
object at once.

Steve
 
R

Rasputin

You need to bear in mind the _depth_ at which you are synchronizing. For
example, java.util.Vector is a synchronized collection and _might_ do what
you want, but remember that you are only synchronizing while you are in
the get(int index) method. This is over in microseconds. Now you have your
reference to an Object in the Vector, and are free to use the reference to
access the Object BUT such access is not synchronized! This could be good
or bad, depending on your code. Good because your object manipulation can
happen in multithreaded parallel heaven, bad because you _might_ still
need to worry about concurrent access/modification of the Objects
contained in the Vector.
Again, don't confuse synchronized access to a Collection with any
subsequent access to the retrieved Objects. With Vector, all accesses (add
delete, get) are synchronized. This is as it should be, to prevent get()
from misreading a partially modified structure.

As an additional question, would you still have the concurrency
issues if you were defensively copying the objects returned by getObject()?

That would seem to solve both problems...but would it gain you anything if
Vector is explicitly synchronized?
 
A

Agustin Chernitsky

Hi Adam,

So actually, I can pull an obj reference from the array, and in the meantime
another thread can remove that obj from the array?

That means I will get a null pointer...

I will have to hold the lock a little more then...

Thanks!
 
J

Joseph Millar

I wasn´t aware of mutex. It sounds like the best solution. Do you know a
Internet site were I could learn more about this? I will try and get the
book meanwhile...

Use of mutexes and other semaphore and thread syncronization
controls are not exclusive to Java and can be found in any
decent text on multithreading and concurrent programming.
For a Java specific treatment, you might try:

"Concurrent Programming in Java" by Doug Lea

I think this book is in it's 2nd edition, you can find it
in any decent technical bookstore or online book sites, like
Amazon or Safari, etc.

Good luck.

--Joe
 
S

Steve Horsley

(e-mail address removed)_SPAM.net wrote in comp.lang.java.programmer:



As an additional question, would you still have the concurrency issues
if you were defensively copying the objects returned by getObject()?

That would seem to solve both problems...but would it gain you anything
if Vector is explicitly synchronized?

Ah yes, but...
You need to ensure that no-one else modifies the object while you are
making the copy. So you still need to synchronize on the retireved object
for a while. Whether it is better to make the required changes to the
object directly, or better to make a copy and then modify that depend on
how long the real work takes.

If you make a copy and edit that, you have the hassle of deleting the old
copy and inserting the new copy in the container when you've finished,
which really needs to be an atomic operation, so you need to synchronize
on the container while you do the switch (or add a synchronized replace
method).


Vector being synchronized has no bearing on this discussion. Imagine this:

* Thread A retrieves a reference to an object from a Vector.
* Thread B then retrieves a reference to the same object.
(The above MUST happen sequentially because Vector is synchronized.)
* Thread A begins modifying the object's contents.
* Thread B begins modifying the object's contents.
* Thread B finishes modifying the object.
* Thread A finishes modifying the object.
The object's contents are now a complete mess of a mixture between what A
and B were doing.

Make sure you understand what a horrible mess this can make.
The synchronized Vector will prevent you getting the wrong object reference,
or null, but you must still somehow make sure that the object update isn't
done by 2 threads at once. There are two separate issues:
* Updating the Vector's data (add/delete object references)
* Updating an object's contents

Steve
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top