lock(this) hangs

R

Rainer Queck

Hello NG,

my application hangs onec a while. When I interrupt the execution (press the
|| button) the debugger shows me a green arrow on a "lock(this)" line.
I first thought, well "deadlock" so I modified my code to find out who locks
the app. Therfore I added a string member "lockOwner" to the class in
question and after each "lock(this)" I set the members value to the method
name like:

lock(this)
{
lockOwner = "Method1";
}
lockOwner = "unlocked";

As I ran into the same hang situation again, I thought, I could now find out
which method causes the problem, but o wonder....
lowOwner showed "unlocked" !!
I tripple checked, that I did not miss a lockOwner assignement.
Now I am out of any ideas to find the cause to my problem.

I would very much appreceate any hints and help on this issue.

Regards
Rainer Queck
 
M

Marc Gravell

First off, setting lockOwner to "unlocked" *outside* of the lock is
going to be a problem. Consider the timeline:

Thread A: Aquires lock and sets lockOwner
Thread B: Waits for lock
Thread A: Releases lock
Thread B: Aquires lock and sets lockOwner
Thread A: Sets lockOwner to "Unknown"

Now thread B has the lock, but lockOwner is "Unknown". If you want to
do it this way, you'd need something more like:

lock({lock object}) {
lockOwner = "Me";
try {
// do something
} finally {
lockOwner = "";
}
}

which is clearly a pain.

Second; I don't recommend locking on "this"; you can never know who
else is locking any object, so it is a poor choice. For less chance of
deadlocks, keep a private object for the purpose - or sometimes you
can re-use a handy *private* readonly object (such as an inner
collection that is not exposed).

Did you check what the other threads were doing? That is perhaps the
easiest way of finding what is doing what.

If the problem is two threads aquiring locks in different orders, then
Jon Skeet has an interesting article (below) that I once used very
successfully to find the offenders.

http://www.pobox.com/~skeet/csharp/miscutil/usage/locking.html

If you give more information about your scenario (are you using
Control.Invoke, for example) there may be other nuggets of advice - or
post *small but complete* code for a more thorough review.

Marc
 
R

Rainer Queck

Hello Mark,

thanks for you very helpful hints!
First off, setting lockOwner to "unlocked" *outside* of the lock is
going to be a problem. Consider the timeline:

Thread A: Aquires lock and sets lockOwner
Thread B: Waits for lock
Thread A: Releases lock
Thread B: Aquires lock and sets lockOwner
Thread A: Sets lockOwner to "Unknown"
Good point! Forgot to consider this.
Second; I don't recommend locking on "this"; you can never know who
else is locking any object, so it is a poor choice. For less chance of
deadlocks, keep a private object for the purpose - or sometimes you
can re-use a handy *private* readonly object (such as an inner
collection that is not exposed).
In general you are right.
In my case I KNOW that nobody else is locking "this" object, becaues in my
project I am using lock(this) only inside a class.
Did you check what the other threads were doing? That is perhaps the
easiest way of finding what is doing what.
How can I do this?
If the problem is two threads aquiring locks in different orders, then
Jon Skeet has an interesting article (below) that I once used very
successfully to find the offenders.

http://www.pobox.com/~skeet/csharp/miscutil/usage/locking.html
Thanks for the link. I will read this next.
If you give more information about your scenario (are you using
Control.Invoke, for example) there may be other nuggets of advice - or
post *small but complete* code for a more thorough review.
That will be difficult, since I am working on this project nearly a year now
and it is kind of komplex.
I doubt it, that I can generate a *smal but complete* code from it, that
would show the issue.

Thanks to your hints, I now have some more ideas to continue debugging my
issue.

Regards
Rainer
 
M

Marc Gravell

How can I do this?
In VS Pro (or above), bring up the threads window; [Ctrl]+[D],[T] if I
recall; likewise, [Ctrl]+[D],[C] brings up the call stack (change
thread in the thread window to see the different call stacks). If the
key-chords don't work, they are on the Debug->Windows menu.
That will be difficult, since I am working on this project nearly a year now
and it is kind of komplex.
I doubt it, that I can generate a *smal but complete* code from it, that
would show the issue.
This is often the case with threading; fair enough ;-p

Marc
 
M

Marc Gravell

To highlight; in a winform, a common cause of deadlock is
Control.Invoke - i.e. (just one scenario) a worker thread locks an
object then calls Control.Invoke to get to the UI thread and invoke
something that attempts to lock the same object. The UI thread can't
get the lock, and the worker thread is blocked on the UI. So check for
Control.Invoke methods at the top of the call-stack.

Marc
 
R

Rainer Queck

Hi Marc,

thanks once more for your help.

Marc Gravell said:
To highlight; in a winform, a common cause of deadlock is
Control.Invoke - i.e. (just one scenario) a worker thread locks an
object then calls Control.Invoke to get to the UI thread and invoke
something that attempts to lock the same object. The UI thread can't
get the lock, and the worker thread is blocked on the UI. So check for
Control.Invoke methods at the top of the call-stack.
Very likely that this is the reason to my issue.
Also your link to "MiscUtil" came just in time sine I decided to rethink my
sync- and locking strategys .
I have read the article, and I think I will make use of SyncLock instead of
lock().
As I saw the SyncLock has a name property. I hope I can "misuse" this to
assign a owner to it, therby knowing who is holding it.

Thanks a lot!
Rainer
 
J

Jon Skeet [C# MVP]

As I saw the SyncLock has a name property. I hope I can "misuse" this to
assign a owner to it, therby knowing who is holding it.

No need to do that - use OrderedLock instead, as it has an Owner
property which tells you which thread currently owns it.

I have an outstanding issue reported to me around OrderedLock and using
it for Monitor.Wait/Pulse, but if you don't use those it should be
fine.
 
R

Rainer Queck

Hi Jon,

Jon Skeet said:
No need to do that - use OrderedLock instead, as it has an Owner
property which tells you which thread currently owns it.
Thank you very much for this hint - and of course for providing this
MiscUtil library -. Actually I already decided to use OrderedLock for "the
other" reason ;-) but I wasn't aware of the Owner Property. That will make
things a lot easier.
I have an outstanding issue reported to me around OrderedLock and using
it for Monitor.Wait/Pulse, but if you don't use those it should be
fine.
At the moment I am not planing to use Monitor.Wait/Pulse.,

Regards
Rainer
 
M

Marra

You are really opening up a can of nasty worms with multi threaded
programs.

I tend to shy away from them as I find some of my routines are more
than complicated enough without adding in the dangers of threading
them.

The only thing I have used threads on is clearing huge buggers where I
split the task into four threads, each thread clearing a quarter of
the buffer.
 
J

Jon Skeet [C# MVP]

Marra said:
You are really opening up a can of nasty worms with multi threaded
programs.

Threading is certainly difficult - but it's important, and going to be
increasingly so as manufacturers add more and more cores to chips.
I tend to shy away from them as I find some of my routines are more
than complicated enough without adding in the dangers of threading
them.

What do you do to keep UIs responsive? The key to keeping a UI
responsive is to not do significant processing on the UI thread. That
pretty much necessitates threading in many applications.

You certainly need to be careful when threading, and it's worth
considering whether or not something really needs to be multi-threaded
before making it so - but it's also not something to be avoided like
the plague.
 
M

Marc Gravell

You are really opening up a can of nasty worms with multi threaded
programs.

The can exists either way. It is just a different label ;-p As Jon
already said, keeping the UI responsive is a major aim in non-trivial
apps (and DoEvents() is *not* a good solution to this) - but I agree
that *improper* use of threading can cause major headaches. There are
several approaches you can use to keep things simple - for example, in
a simple worker/UI scenario there is often no need for the two to
share data except when throwing data onto the UI (via Invoke/
BeginInvoke) - which can remove the need for a lot of complicated
locking.

But more than this - as PCs become more CPU rich (multiple slower
cores rather than a single speedy core), ginving *suitable*
consideration to threading is a good skill to learn. And that doesn't
mean "multi-thread everywhere". Equally, frameworks like PFX (or
Parallel Extensions as it is now) show where *some* (but definitely
not all) code is heading.

Marc
 
G

Göran Andersson

Rainer said:
In general you are right.
In my case I KNOW that nobody else is locking "this" object, becaues in my
project I am using lock(this) only inside a class.

No, you can't KNOW that. As long as you are using a publically reachable
object, any other code can potentially use the same object for locking.

If you instead use a private object for locking, you KNOW that no other
code can use the same object for locking.
 

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

Top