Multi-Object SyncLock?

  • Thread starter Thread starter Frank Osterberg
  • Start date Start date
F

Frank Osterberg

Hi,



I want to simultaneously SyncLock multiple objects, something like:

SyncLock objA, objB

' do stuff with objA and objB

End SyncLock



but so that a lock is only obtained if BOTH objects can be locked obtained
simultaneously.



I want to prevent possible deadlocks when multiple threads lock these
objects conditionally and out of order.



Is that possible and if so how?



Thanks,



Frank
 
Hi Frank,


Something like this?


SyncLock objA

SyncLock objB

End SyncLock

End SyncLock




Robin
 
Something like this?
SyncLock objA
SyncLock objB
End SyncLock
End SyncLock

That could lead to a deadly embrace if another thread does this:

SyncLock objB
SyncLock objA
End SyncLock
End SyncLock
 
That could lead to a deadly embrace if another thread does this:
SyncLock objB
SyncLock objA
End SyncLock
End SyncLock

Deadlock indeed.

However, the only other thing I can think of is to encapsulate the objects
that require locking into one object and to lock that.
 
Robin Tucker said:
Deadlock indeed.

However, the only other thing I can think of is to encapsulate the objects
that require locking into one object and to lock that.
Yea, I was getting deadlocks.

The problem is that it was not just two items, but there is a list of items
and different threads iterate through the list and try to modify some item
and if needed a related item. That related item might itself be the related
item of another item being modified by another thread, hence the problem.

Well I found that I could at least create an ugly but workable workaround
using Monitor.TryEnter:

Dim worked As Boolean = False
While Not worked
SyncLock objA
worked = Threading.Monitor.TryEnter(objB, 100)
If worked Then
Try
' Do Stuff
Catch ex As Exception
Throw ex
Finally
Threading.Monitor.Exit(objB)
End Try
End If
End SyncLock
End While

But I don't like it one bit since it doesn't automatically release the lock
(hence I need the try catch finally).

Is there a better way?

In any case, thanks for the help!
 
Either way, you should have a public interface to access all of the objects
in one place. You can then lock all objects on this one common instance.
So create a new class, encapsulating the objects shared accross threads,
then lock on that. All you need to do is pass the accessor instance to each
thread and make sure the accessor instance contains references to the
objects the threads want to manipulate. Then you can:

SyncLock ( MyAccessor )

MyAccessor .Obj1.....

MyAccessor .Obj2.....

End SyncLock
 
The problem is that it was not just two items, but there is a list of items
and different threads iterate through the list and try to modify some item
and if needed a related item. That related item might itself be the related
item of another item being modified by another thread, hence the problem.

you could synclock with the object that represents your 'list of items', ie
the array or the collection or whatever. i know it is a blunt instrument
approach, but it will work. if you go this way, then thread 1 using objects
a and b will block thread 2 that wants to use (unrelated) objects c and d.
It is hard to imagine a case where this creates a problem.
 
AMercer said:
you could synclock with the object that represents your 'list of items',
ie
the array or the collection or whatever. i know it is a blunt instrument
approach, but it will work. if you go this way, then thread 1 using
objects
a and b will block thread 2 that wants to use (unrelated) objects c and d.
It is hard to imagine a case where this creates a problem.

So simply, i can't believe i didn't think of it >_<;

Thank you!
 
Robin Tucker said:
Either way, you should have a public interface to access all of the
objects in one place. You can then lock all objects on this one common
instance. So create a new class, encapsulating the objects shared accross
threads, then lock on that. All you need to do is pass the accessor
instance to each thread and make sure the accessor instance contains
references to the objects the threads want to manipulate. Then you can:

SyncLock ( MyAccessor )

MyAccessor .Obj1.....

MyAccessor .Obj2.....

End SyncLock

True & works! For some reason i didn't think of that ;)

Thank you!
 
Frank,
I want to simultaneously SyncLock multiple objects, something like:

SyncLock objA, objB

' do stuff with objA and objB

End SyncLock

There doesn't have to be any relation between the object you lock on
and the object(s) you're going to work with inside the synchonized
block. You can lock on any object, as long as all threads that are
working with the data lock on the same object. Often it's a good idea
to have a completely separate object dedicated only for the locking,
it helps avoid this confusion.


Mattias
 
Frank Osterberg said:
The problem is that it was not just two items, but there is a list of
items and different threads iterate through the list and try to modify
some item and if needed a related item. That related item might itself be
the related item of another item being modified by another thread, hence
the problem.

You might take a look at:
http://www.coversant.net/Default.aspx?tabid=88&EntryID=40

In there, I go over some of the approaches I've used (and liked / didn't
like) for solving this problem.
 
Back
Top