469,649 Members | 1,469 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,649 developers. It's quick & easy.

lock problem

Hi all.
I have an ArrayList and
sometimes while enumerating through, i get an
exception because another thread has added to the ArrayList.
To solve this problem, i lock the enumeration,
passing the ArrayList instance to the lock.
But i still get the same exception.
Thanks for your help.
Sharon.
Nov 16 '05 #1
14 6075

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
Hi all.
I have an ArrayList and
sometimes while enumerating through, i get an
exception because another thread has added to the ArrayList.
To solve this problem, i lock the enumeration,
passing the ArrayList instance to the lock.
But i still get the same exception.
Thanks for your help.
Sharon.

Nov 16 '05 #2
The ArrayList.

"Angel J. Hernández" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
Hi all.
I have an ArrayList and
sometimes while enumerating through, i get an
exception because another thread has added to the ArrayList.
To solve this problem, i lock the enumeration,
passing the ArrayList instance to the lock.
But i still get the same exception.
Thanks for your help.
Sharon.


Nov 16 '05 #3
Try locking the Syncronized ;-)

"Sharon" <sh****@void.null> escribió en el mensaje
news:eR**************@TK2MSFTNGP10.phx.gbl...
The ArrayList.

"Angel J. Hernández" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
> Hi all.
> I have an ArrayList and
> sometimes while enumerating through, i get an
> exception because another thread has added to the ArrayList.
> To solve this problem, i lock the enumeration,
> passing the ArrayList instance to the lock.
> But i still get the same exception.
> Thanks for your help.
> Sharon.
>
>



Nov 16 '05 #4

"Sharon" <sh****@void.null> wrote in message
news:eR**************@TK2MSFTNGP10.phx.gbl...
The ArrayList.


Are the other threads locking the arraylist when they insert items?

Are you maintaining the lock for the duration of the enumeration?

Daviv
Nov 16 '05 #5
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}

And not this way:
lock(arrayListInstance)
{
enumerate...
}

"Angel J. Hernández" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
Hi all.
I have an ArrayList and
sometimes while enumerating through, i get an
exception because another thread has added to the ArrayList.
To solve this problem, i lock the enumeration,
passing the ArrayList instance to the lock.
But i still get the same exception.
Thanks for your help.
Sharon.


Nov 16 '05 #6
Nop... I owe you an apology. I wrote Syncronized instead of SyncRoot :$

I meant something like this...

ArrayList al = new ArrayList();

lock(al.SyncRoot) {
foreach(object item in al) {
// Enumerate
}
}
Regards

"Sharon" <sh****@void.null> escribió en el mensaje
news:Om**************@TK2MSFTNGP09.phx.gbl...
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}

And not this way:
lock(arrayListInstance)
{
enumerate...
}

"Angel J. Hernández" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
> Hi all.
> I have an ArrayList and
> sometimes while enumerating through, i get an
> exception because another thread has added to the ArrayList.
> To solve this problem, i lock the enumeration,
> passing the ArrayList instance to the lock.
> But i still get the same exception.
> Thanks for your help.
> Sharon.
>
>



Nov 16 '05 #7
I have to say that I think lock to be maybe the worst named keyword in the language. It gives the impression that it imposes some kind of invisible force field around the object in question that cannot be pierced by other code until the code block executes. This unfortunately is rubbish.

lock(obj)
{
// some thread sensitive code here
}

translates to

Monitor.Enter(obj);
try
{
// some thread sensitive code here
}
finally
{
Monitor.Exit(obj);
}

and all Monitor.Enter (simplistically) does is manipulate the SyncBlock in the objects header. Conceptually It stamps its thread id against the SyncBlock. If another thread id is already stamped there it blocks until the SyncBlock becomes "un-owned" then proceeds to stamp its thread id against the SyncBlock. Monitor.Exit clears the threads id from the syncblock.

So simply stating lock() on anything at all (even if it is the SyncRoot) will achieve nothing UNLESS all code that is accessing the rescource ALSO calls lock on the same thing. In other words

lock(obj)
{
// access some shared. thread sensitive resource
}

only guarantees thread synchronization if all code calls lock(obj), obj being the same physical object as above, before accessing the shared resource.

With collections you can create a thread safe wrapper wound the collection using the Synchronized method - but all this does is do the appropriate locking internally.

One final thing about lock. lock is a block with no timeout. If you get a thread deadlock your application is hosed. The Monitor class also has a TryEnter method which you can pass a timeout to. Ian Griffiths has written a nice wrapper for this which allows you to use stcks based release using the "using" keyword. Heres the URL

http://www.interact-sw.co.uk/iangblo.../03/23/locking

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<ug*************@tk2msftngp13.phx.gbl>

Nop... I owe you an apology. I wrote Syncronized instead of SyncRoot :$

I meant something like this...

ArrayList al = new ArrayList();

lock(al.SyncRoot) {
foreach(object item in al) {
// Enumerate
}
}
Regards

"Sharon" <sh****@void.null> escribi? en el mensaje
news:Om**************@TK2MSFTNGP09.phx.gbl...
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}

And not this way:
lock(arrayListInstance)
{
enumerate...
}

"Angel J. Hern?ndez" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hern?ndez M.
MCSD

"Sharon" <sh****@void.null> escribi? en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
> Hi all.
> I have an ArrayList and
> sometimes while enumerating through, i get an
> exception because another thread has added to the ArrayList.
> To solve this problem, i lock the enumeration,
> passing the ArrayList instance to the lock.
> But i still get the same exception.
> Thanks for your help.
> Sharon.
>
>




---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004

[microsoft.public.dotnet.languages.csharp]
Nov 16 '05 #8
I realise that my post was incomplete - I didn't address the SyncRoot issue. Take the following code:

static void Main(string[] args)
{
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());

Thread t = new Thread(new ThreadStart(Ouch));
t.Start();

lock(arr.SyncRoot)
{
foreach(object o in arr)
{
Thread.Sleep(1000);
o.ToString();
}
}
}

static void Ouch()
{
Thread.Sleep(1000);
arr.RemoveAt(0);
}

This throws an InvalidOperationException because the collection was modified during iteration by the Ouch method running on the other thread. In other words, the SyncRoot is useless on its own in the default case. However, add the following line of code just before the creation of the Thread object (or at least before the thread is started).

arr = ArrayList.Synchronized(arr);

This creates a thread safe wrapper around the arraylist with operations locking the SyncRoot internally. Now the code will perform correctly as the foreach is synchronized with the modifications.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<e3*************@TK2MSFTNGP15.phx.gbl>

I have to say that I think lock to be maybe the worst named keyword in the language. It gives the impression that it imposes some kind of invisible force field around the object in question that cannot be pierced by other code until the code block executes. This unfortunately is rubbish.

lock(obj)
{
// some thread sensitive code here
}

translates to

Monitor.Enter(obj);
try
{
// some thread sensitive code here
}
finally
{
Monitor.Exit(obj);
}

and all Monitor.Enter (simplistically) does is manipulate the SyncBlock in the objects header. Conceptually It stamps its thread id against the SyncBlock. If another thread id is already stamped there it blocks until the SyncBlock becomes "un-owned" then proceeds to stamp its thread id against the SyncBlock. Monitor.Exit clears the threads id from the syncblock.

So simply stating lock() on anything at all (even if it is the SyncRoot) will achieve nothing UNLESS all code that is accessing the rescource ALSO calls lock on the same thing. In other words

lock(obj)
{
// access some shared. thread sensitive resource
}

only guarantees thread synchronization if all code calls lock(obj), obj being the same physical object as above, before accessing the shared resource.

With collections you can create a thread safe wrapper wound the collection using the Synchronized method - but all this does is do the appropriate locking internally.

One final thing about lock. lock is a block with no timeout. If you get a thread deadlock your application is hosed. The Monitor class also has a TryEnter method which you can pass a timeout to. Ian Griffiths has written a nice wrapper for this which allows you to use stcks based release using the "using" keyword. Heres the URL

http://www.interact-sw.co.uk/iangblo.../03/23/locking

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<ug*************@tk2msftngp13.phx.gbl>

Nop... I owe you an apology. I wrote Syncronized instead of SyncRoot :$

I meant something like this...

ArrayList al = new ArrayList();

lock(al.SyncRoot) {
foreach(object item in al) {
// Enumerate
}
}
Regards

"Sharon" <sh****@void.null> escribi? en el mensaje
news:Om**************@TK2MSFTNGP09.phx.gbl...
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}

And not this way:
lock(arrayListInstance)
{
enumerate...
}

"Angel J. Hern?ndez" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hern?ndez M.
MCSD

"Sharon" <sh****@void.null> escribi? en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
> Hi all.
> I have an ArrayList and
> sometimes while enumerating through, i get an
> exception because another thread has added to the ArrayList.
> To solve this problem, i lock the enumeration,
> passing the ArrayList instance to the lock.
> But i still get the same exception.
> Thanks for your help.
> Sharon.
>
>




---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004

[microsoft.public.dotnet.languages.csharp]

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004

[microsoft.public.dotnet.languages.csharp]
Nov 16 '05 #9
Richard Blewett [DevelopMentor] <ri******@develop.com> wrote:
I realise that my post was incomplete - I didn't address the SyncRoot
issue. Take the following code:

static void Main(string[] args)
{
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());

Thread t = new Thread(new ThreadStart(Ouch));
t.Start();

lock(arr.SyncRoot)
{
foreach(object o in arr)
{
Thread.Sleep(1000);
o.ToString();
}
}
}

static void Ouch()
{
Thread.Sleep(1000);
arr.RemoveAt(0);
}

This throws an InvalidOperationException because the collection was
modified during iteration by the Ouch method running on the other
thread. In other words, the SyncRoot is useless on its own in the
default case. However, add the following line of code just before the
creation of the Thread object (or at least before the thread is
started).

arr = ArrayList.Synchronized(arr);

This creates a thread safe wrapper around the arraylist with
operations locking the SyncRoot internally. Now the code will perform
correctly as the foreach is synchronized with the modifications.


Note that you don't have to use ArrayList.Synchronized to use SyncRoot
though - if Ouch() had been written:

static void Ouch()
{
Thread.Sleep(1000);
lock (arr.SyncRoot)
{
arr.RemoveAt(0);
}
}

it would have been fine.

Personally I don't like ArrayList.Synchronized - I think it's better to
make it obvious when you're locking like this. That's just MHO though.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #10
But in that case there is nothing special about the SyncRoot and everyone may as well just lock the ArrayList itself. The SyncRoot only has a unique purpose if the ArrayList (or other collection) is Synchronized.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<MP************************@msnews.microsoft.com >

Richard Blewett [DevelopMentor] <ri******@develop.com> wrote:
I realise that my post was incomplete - I didn't address the SyncRoot
issue. Take the following code:

static void Main(string[] args)
{
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());
arr.Add(new object());

Thread t = new Thread(new ThreadStart(Ouch));
t.Start();

lock(arr.SyncRoot)
{
foreach(object o in arr)
{
Thread.Sleep(1000);
o.ToString();
}
}
}

static void Ouch()
{
Thread.Sleep(1000);
arr.RemoveAt(0);
}

This throws an InvalidOperationException because the collection was
modified during iteration by the Ouch method running on the other
thread. In other words, the SyncRoot is useless on its own in the
default case. However, add the following line of code just before the
creation of the Thread object (or at least before the thread is
started).

arr = ArrayList.Synchronized(arr);

This creates a thread safe wrapper around the arraylist with
operations locking the SyncRoot internally. Now the code will perform
correctly as the foreach is synchronized with the modifications.


Note that you don't have to use ArrayList.Synchronized to use SyncRoot
though - if Ouch() had been written:

static void Ouch()
{
Thread.Sleep(1000);
lock (arr.SyncRoot)
{
arr.RemoveAt(0);
}
}

it would have been fine.

Personally I don't like ArrayList.Synchronized - I think it's better to
make it obvious when you're locking like this. That's just MHO though.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.770 / Virus Database: 517 - Release Date: 27/09/2004

[microsoft.public.dotnet.languages.csharp]
Nov 16 '05 #11
Richard Blewett [DevelopMentor] <ri******@develop.com> wrote:
But in that case there is nothing special about the SyncRoot and
everyone may as well just lock the ArrayList itself. The SyncRoot
only has a unique purpose if the ArrayList (or other collection) is
Synchronized.


Well, unless the collection is derived from another one - eg the
collection returned by Hashtable.Values has the same SyncRoot as the
hashtable itself.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #12
Hi,

I suggest you this way:

//Get a sync copy

ArrayList arSynced = ArrayList.Synchronized( theArrayList )

It does assure sync using ArrayList.SyncRoot , now you can safety do

lock( arSynced.SyncRoot )
{
//enumerate
}

if another thread do a arSynced.Add( object ) it will work OK !!
Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

"Sharon" <sh****@void.null> wrote in message
news:Om**************@TK2MSFTNGP09.phx.gbl...
Should i try it this way:
lock(ArrayList.Synchronized(arrayListInstance))
{
enumerate...
}

And not this way:
lock(arrayListInstance)
{
enumerate...
}

"Angel J. Hernández" <an**********@hotmail.com> wrote in message
news:Ob**************@TK2MSFTNGP12.phx.gbl...

Are you locking the ArrayList or ArrayList.Syncronized property?

Regards,
--
Angel J. Hernández M.
MCSD

"Sharon" <sh****@void.null> escribió en el mensaje
news:%2*****************@TK2MSFTNGP09.phx.gbl...
Hi all.
I have an ArrayList and
sometimes while enumerating through, i get an
exception because another thread has added to the ArrayList.
To solve this problem, i lock the enumeration,
passing the ArrayList instance to the lock.
But i still get the same exception.
Thanks for your help.
Sharon.



Nov 16 '05 #13
Thanks for your help.
As i understand it, the Synchronized wrapper uses the collection SyncRoot
on every call.
And that is why, using only the wrapper will not work in this case.
Because the collection is not locked between enumerator internal operations.
Using the wrapper and locking SyncRoot during enumeration will work,
but i thinks it's better, to lock SyncRoot during enumeration,
and use SyncRoot when adding or removing.
Sharon.
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Richard Blewett [DevelopMentor] <ri******@develop.com> wrote:
But in that case there is nothing special about the SyncRoot and
everyone may as well just lock the ArrayList itself. The SyncRoot
only has a unique purpose if the ArrayList (or other collection) is
Synchronized.


Well, unless the collection is derived from another one - eg the
collection returned by Hashtable.Values has the same SyncRoot as the
hashtable itself.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 16 '05 #14
Sharon <sh****@void.null> wrote:
As i understand it, the Synchronized wrapper uses the collection SyncRoot
on every call.
And that is why, using only the wrapper will not work in this case.
Because the collection is not locked between enumerator internal operations.
Using the wrapper and locking SyncRoot during enumeration will work,
but i thinks it's better, to lock SyncRoot during enumeration,
and use SyncRoot when adding or removing.


Exactly.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

2 posts views Thread by xixi | last post: by
7 posts views Thread by Sunny | last post: by
reply views Thread by Nashat Wanly | last post: by
14 posts views Thread by Gary Nelson | last post: by
reply views Thread by cburnett | last post: by
2 posts views Thread by WingSiu | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.