Problems with synchronizing an element in an array

I have a class that extends ArrayList. I have another class called "Elem" that works as elements for the ArrayList. Multiple threads will work on this list.

When I get an element from the ArrayList I would like to lock only this element so another thread can delete other elements in the list.

I have made this method for getting and locking an element:

public String get(int id)

{

String res ="No such file, try command list";

int size = this.size();

for (int i = 0; i<size;i++)

{

Elem ifo = (Elem)this.get(i);

if(ifo.getId() == id)

{

synchronized(ifo)

{

try{

Thread.sleep(4000);

}catch (InterruptedException e){

e.printStackTrace();

}

res = ifo.getData() +" Received";

}

break;

}

}

return res;

}

I have made the operation last for 4 seconds because I test if the object is locked with the follwing delete method:

publicsynchronized String del(int id)

{

String res =" no file";

int size = this.size();

for (int i = 0; i><size;i++)

{

Elem ifo = (Elem)this.get(i);

if(ifo.getId() == id)

{

super.remove(ifo);

res = ifo.getId() +" deleted!";

break;

}

}

return res;

}

But when I run the program and start reading an element that I try to delete at the same time it gets deleted! Why does the "del" method not block until the element has been read?>

[2755 byte] By [lokpesta] at [2007-10-3 4:49:01]
# 1

For what you are actually trying to do I would suggest that the get method actually removes the element from the List. Perhaps you could rename this method getExclusive or something...

Anyway when you are done put it back.

Because synchonrization doesn't work in a fashion that your code demonstrates that you would like it to.

cotton.ma at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 2

> I have a class that extends ArrayList. I have another

> class called "Elem" that works as elements for the

> ArrayList. Multiple threads will work on this list.

>

> When I get an element from the ArrayList I would like

> to lock only this element so another thread can

> delete other elements in the list.

That won't work. Deleting elements from the list modifies the list, not the elments, so you need to sync on the list. Only one thread at a time can add to or delete from a list.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 3
Ok if I remove it then there is no point in using synchronized because the "del" method will never find it.Is it not possible to synchronize a single element in an array and keep other threads from manipulating it until the thread has finished doing its work?
lokpesta at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 4

> Ok if I remove it then there is no point in using

> synchronized because the "del" method will never find

> it.

>

Well there is still is a point to synchronizing that method. Otherwise chaos!

> Is it not possible to synchronize a single element in

> an array and keep other threads from manipulating it

> until the thread has finished doing its work?

No.

cotton.ma at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 5

> Ok if I remove it then there is no point in using

> synchronized because the "del" method will never find

> it.

If there are multiple threads adding to and/or removing from the list, you must sync all those remove operations on a common lock--usually the list itself.

> Is it not possible to synchronize a single element in

> an array and keep other threads from manipulating it

> until the thread has finished doing its work?

You can sync on a single element, of course--it's just another object. But that does not help you if you're removing that object, because any add or remove operation will operate on data that is shared by all add and remove operations.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 6
Ok but that is pretty ineffective. In real systems its possible for a user to read one file on the disk while deleting another. I try to simulate a disk with an ArrayList and obtain the same functionality but since its impossible how is it acomplished in real systems?
lokpesta at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 7

> Ok but that is pretty ineffective. In real systems

> its possible for a user to read one file on the disk

> while deleting another. I try to simulate a disk with

> an ArrayList and obtain the same functionality but

> since its impossible how is it acomplished in real

> systems?

What is pretty ineffective? My solution? My solution is perfectly effective and provides the functionality you seek.

If you really wanted to do it like a disk then I would wrap your objects in an object that has a boolean lock added to it.

When you retrieve the element then you mark the item as locked (all in a synchronized method).

Then when you go to delete you don't allow locked items to be deleted.

Of course you still have to release the lock...

cotton.ma at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 8
No it was not your suggestion that I found ineffctive its the fact that its not possible to make multiple operations on a list at the same time.
lokpesta at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 9

> Ok but that is pretty ineffective.

No, it works well in many situations.

> In real systems

> its possible for a user to read one file on the disk

> while deleting another.

That doesn't necessarily translate directly to what you've said so far.

> I try to simulate a disk with

> an ArrayList and obtain the same functionality but

> since its impossible how is it acomplished in real

> systems?

This sounds different from what you were asking about earlier.

WIthout more details about what you're trying to do and how you're trying to implement it, it's hard to advise you how to solve your problem.

Also, note that even things that appear to be "simultaneous" may have synchronized pieces that happen so quickly that you can't tell the difference.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 10

> > Is it not possible to synchronize a single element in

> > an array and keep other threads from manipulating it

> > until the thread has finished doing its work?

>

> No.

Actually, you could do anything you liked if you encapsulated the array in an object and required all access to the array to be via methods of the object. But just leaving the array out there on the floor for everybody to kick at, "no" is the answer.

DrClapa at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 11

> No it was not your suggestion that I found ineffctive

> its the fact that its not possible to make multiple

> operations on a list at the same time.

Nobody said it's not possible to make multiple operations on a list at the same time.

What we said is that you must synchronize any operations that add or remove data in a java.util.ArrayList (and other standard collections) because those add and remove operations modify shared data.

Anytime multiple threads might be modifying shared data, you must synchronize. Or else you must be able to detect and correct any inconsistencies that arise from lack of syncing.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 12

> > > Is it not possible to synchronize a single

> element in

> > > an array and keep other threads from manipulating

> it

> > > until the thread has finished doing its work?

> >

> > No.

>

> Actually, you could do anything you liked if you

> encapsulated the array in an object and required all

> access to the array to be via methods of the object.

But there'd still have to be synchronization at some point in those methods, because shared data might be modified by multiple threads.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 13

Ok here is what I am trying to do.

1) Thread 1 get an element from list A. At the SAME time thread 2 deletes a different element from list A.

2) Thread 1 get an element from list A. At the same time thread 2 tries to delete the same item but gets blocked since thread 1 is reading it.

currently only serial execution works, since all the methods on the list are synchronized.

lokpesta at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 14

> Ok here is what I am trying to do.

>

>

> 1) Thread 1 get an element from list A. At the SAME

> time thread 2 deletes a different element from list

> A.

Everything I've said still applies. What do you mean "at the SAME time"? And why does it have to be "at the SAME time"? What if whatever triggers cause the two actions happen "at the SAME time," but the actual actions happen a millisecond apart?

> currently only serial execution works, since all the

> methods on the list are synchronized.

Again, anytime you're accessing shared data from multiple threads, you must synchronize. That syncing may be very, very brief--say just to atomically update a counter or "available" bitmap or something, but if there's shared data--such as a bitmap that keeps track of which slots are used--read/updates, like "find an available one, mark it used, and give me its index"--must be atomic, so there must be some synchronization.

Or else different threads get different sections of the array assigned to them.

jverda at 2007-7-14 22:53:31 > top of Java-index,Java Essentials,Java Programming...
# 15
Please read replies 1 and 7 and explain what parts of those solution that you are not understanding. I don't need to see your requirements any more. I understand them just fine. You don't seem to be understanding the workable solutions offered.
cotton.ma at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...
# 16
Also read my replies. I haven't paid as much attention to your requirements as cotton, but the principles I described are still relevant.
jverda at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...
# 17

> Also read my replies. I haven't paid as much

> attention to your requirements as cotton, but the

> principles I described are still relevant.

Yes you should read jverd's replies too. He is taking the time to explain to you what is happening in more detail. I am impatient and just trying to address your current problem directly.

So you can go either way (or both). Read and understand jverd's replies so that you can figure it out on your own or implement what I said and

figure out why it works later.

Although besides impatience I also find that when someone has confusion about how something works I find that giving a solution that does work can help because sometimes such persons are more likely to believe what you tell them.

cotton.ma at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...
# 18

well as far as I understand there is no workaround, I need to synchronize when modifying shared data. But all other synchronized methods will be blocked while a single thread executes one of these synchronized methods. Therefore only a single thread can use the array at a time and all the others will block until its finished. This might not be visible to the eye in practice but in theory it a bottleneck.

I am not very experienced with thread safe programs so thanks for your patience so far and I think the best way to get a better understanding would be to find some good litterature since I lack the basic knowledge.

lokpesta at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...
# 19

> well as far as I understand there is no workaround,

Correct. However a better design can make this moot.

> I

> need to synchronize when modifying shared data.

Correct. Sort of.

> But

> all other synchronized methods will be blocked while

> a single thread executes

No.

> one of these synchronized

> methods. Therefore only a single thread can use the

> array at a time and all the others will block until

> its finished.

No.

> This might not be visible to the eye in

> practice but in theory it a bottleneck.

>

If the rest was correct then yes.

> I am not very experienced with thread safe programs

> so thanks for your patience so far and I think the

> best way to get a better understanding would be to

> find some good litterature since I lack the basic

> knowledge.

Think of it this way you want to spend the least time in the synchronized block as possible right?

So you need to either remove the object you want to modify from the shared list OR taint it so that other threads know that it is locked from delettion.

As soon as that part is done (which wouldn't take very long) you can release your synchronized lock and the next thread can access the shared data.

etc.

cotton.ma at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...
# 20

> well as far as I understand there is no workaround, I

> need to synchronize when modifying shared data. But

> all other synchronized methods will be blocked while

> a single thread executes one of these synchronized

> methods. Therefore only a single thread can use the

> array at a time and all the others will block until

> its finished. This might not be visible to the eye in

> practice but in theory it a bottleneck.

Look, syncing is used all over Java, other programs, OSes, etc. The idea is to keep the sync blocks as small as possible. If it still causes problems, then you have to go with more messy, complex solutions with multiple copies of things, sycning them up in low priority threads, etc. etc. Don't worry about that now. First worry about making it correct.

Syncing to avoid corrupting shared data is a fact of life. If you do it right, it doesn't usually cause performance problems.

> I am not very experienced with thread safe programs

> so thanks for your patience so far and I think the

> best way to get a better understanding would be to

> find some good litterature since I lack the basic

> knowledge.

Indeed. And write some code and play with it, rather than just worrying about what kinds of convoluted machinations you can perform to get around performance problems you're guessing might happen.

"It's easier to optimize a correct program than to correct an optimized program."

--Somebody

Sun's multithreading tutorial:

http://java.sun.com/docs/books/tutorial/essential/concurrency/

Also look for the book Concurrent Programming in Java by Doug Lea.

jverda at 2007-7-21 10:44:21 > top of Java-index,Java Essentials,Java Programming...