Threads - why isn't a whole object locked when ...?

B

beginwithl

hi


1) Say we have an instance A1 of type A. Now if A1 has for example 10
methods, of which two (A_m1 and A_m2) can be locked ( in both methods
we pass ‘this’ as a lock token ), while the remaining methods don’t
use locks, then even if thread T0 calls A_m1 on A, other threads are
still able to call non-locked methods on A( though they get blocked on
calling A_m2()).

Similary, if both threads T0 and T1 call A1.A_m1() at the same time,
but use different object as a lock token, neither of the two threads
will be in blocking mode


a) why, when “this” is used as lock token, isn’t the whole object
locked, and not just methods with locks inside them?

Wouldn’t it be more safe, since some other thread may be using some
other means to access and operate on same members of A1 as A1.A_m1()
is, and thus data may become corrupted?

BTW - I know that one could argue that it is up to the programmer to
make sure that particular data only gets accessed through A1.A_m1(),
but then we could reason as to why use locks at all, since it should
be up to programmer to make sure data doesn’t get corrupted.




b) even if we pass to A1.A_m1() as a lock token some other instance,
and not “this”, wouldn’t it be best if A1 was locked also?




c) say object B is passed as a token to A1.A_m1(). Wouldn’t it make
sense that B was also locked? Afterall, some other thread may be
changing members of B ( not via A1.A_m1 ) at the same time as A1.A_m1
() is operating on those same B members?!





2) Book suggests that if you are locking down a region of code within
apublic member, it is safer to declare a private object member
variable to serve as a token:

class Printer
{
private object threadLock = new object();
public void PrintNumbers()
{
lock ( threadLock )
{ …}
}
}



Now why would having a public token in a public method represent a
security risk:

class Printer
{
public void PrintNumbers()
{
lock ( this )
{

}
}
}



thank you
 
G

Göran Andersson

hi


1) Say we have an instance A1 of type A. Now if A1 has for example 10
methods, of which two (A_m1 and A_m2) can be locked ( in both methods
we pass ‘this’ as a lock token ), while the remaining methods don’t
use locks, then even if thread T0 calls A_m1 on A, other threads are
still able to call non-locked methods on A( though they get blocked on
calling A_m2()).

Similary, if both threads T0 and T1 call A1.A_m1() at the same time,
but use different object as a lock token, neither of the two threads
will be in blocking mode


a) why, when “this” is used as lock token, isn’t the whole object
locked, and not just methods with locks inside them?

Because a lock statement is not protecting the object, it's protecting
the code inside the lock statement. The object in the lock statement is
only used as an identifier.

For a lock to have any effect at all, you have to use the same
identifier in locks around all code that access the same data.
Wouldn’t it be more safe, since some other thread may be using some
other means to access and operate on same members of A1 as A1.A_m1()
is, and thus data may become corrupted?

Yes, it would be safer if we could isolate an object so that only a
certain part of the code could access it, but that is not possible.
BTW - I know that one could argue that it is up to the programmer to
make sure that particular data only gets accessed through A1.A_m1(),
but then we could reason as to why use locks at all, since it should
be up to programmer to make sure data doesn’t get corrupted.

Yes, actually it's up to the programmer to protect the data, and the
lock statement is one of the tools used to do that.
b) even if we pass to A1.A_m1() as a lock token some other instance,
and not “this”, wouldn’t it be best if A1 was locked also?

Which object you use for locking has nothing to do with what you protect
with the lock statement.
c) say object B is passed as a token to A1.A_m1(). Wouldn’t it make
sense that B was also locked? Afterall, some other thread may be
changing members of B ( not via A1.A_m1 ) at the same time as A1.A_m1
() is operating on those same B members?!

No, that doesn't really make sense as you can't lock an object. If you
pass some data into a method that uses a lock, it's up to the method to
protect that data also.
2) Book suggests that if you are locking down a region of code within
apublic member, it is safer to declare a private object member
variable to serve as a token:

class Printer
{
private object threadLock = new object();
public void PrintNumbers()
{
lock ( threadLock )
{ …}
}
}



Now why would having a public token in a public method represent a
security risk:

class Printer
{
public void PrintNumbers()
{
lock ( this )
{

}
}
}



thank you

If you are using a publically accessible member as identifier for the
lock, another method outside the class could use the same object in a
lock and cause a deadlock situation.
 
B

beginwithl

hi

If you are using a publically accessible member as identifier for the
lock, another method outside the class could use the same object in a
lock and cause a deadlock situation.

As for the question about using an internal reference instead of the
"this" reference, the point of that is that the "this" reference is
visible to other code you don't have control over. And if you use "this"
to synchronize, there's a risk that some other code might use the same
reference to synchronize, resulting in a different, unpredicted code path
where the same reference is being used to synchronize. This may lead, at
a minimum, to your own code path getting blocked unexpectedly, and in the
worst case, could lead to a deadlock scenario where that reference is used
in synchronization, along with some other reference as well, but taken in
different orders (a classic way to get into deadlock).


Uh, I don’t get it. I’m prob way off with this --> You mean if I have
a public method A_m1 ( in object A1 ) and I use “this” reference for a
lock inside A_m1, then outside code may at the same time use a
reference to A1 on a lock inside some other method ( which may very-
well be defined in some other class )?
If that is what you guys meant ( which I highly doubt ), then why
would that cause a dead-lock?






(e-mail address removed) wrote:

For a lock to have any effect at all, you have to use the same
identifier in locks around all code that access the same data.


Yes, it would be safer if we could isolate an object so that only a
certain part of the code could access it, but that is not possible.


Yes, actually it's up to the programmer to protect the data, and the
lock statement is one of the tools used to do that.


Which object you use for locking has nothing to do with what you protect
with the lock statement.

I thought it does in cases where object used for locking is also
object the code inside the lock statement is operating on



No, that doesn't really make sense as you can't lock an object. If you
pass some data into a method that uses a lock, it's up to the method to
protect that data also.
What would be the best way to protect that data? If you pass some
object O of type T into a method, then only way you can protect O
( while code in a method is operating on it), is that you somehow make
sure there is no other method ( defined in this or any other class )
operating on that data at the same time.?!
Now since you can’t lock O, I’m not sure how you would manage to
protect it ( assuming some third party created type T and also
assuming app also has some third-party objects that also can operate
on O )?!



thank you
 
A

Arne Vajhøj

Uh, I don’t get it. I’m prob way off with this --> You mean if I have
a public method A_m1 ( in object A1 ) and I use “this” reference for a
lock inside A_m1, then outside code may at the same time use a
reference to A1 on a lock inside some other method ( which may very-
well be defined in some other class )?
If that is what you guys meant ( which I highly doubt ), then why
would that cause a dead-lock?

It would not by itself, but it could under certain circumstances.

Deadlocks occur when:
thread 1 locks on object A
thread 2 locks on object B
thread 1 wait to get lock on B
thread 2 wait to get lock in A

This can happen if there are no clear responsibility for
what code is locking on what objects in what order.

Arne
 
A

Arne Vajhøj

1) Say we have an instance A1 of type A. Now if A1 has for example 10
methods, of which two (A_m1 and A_m2) can be locked ( in both methods
we pass ‘this’ as a lock token ), while the remaining methods don’t
use locks, then even if thread T0 calls A_m1 on A, other threads are
still able to call non-locked methods on A( though they get blocked on
calling A_m2()).

Similary, if both threads T0 and T1 call A1.A_m1() at the same time,
but use different object as a lock token, neither of the two threads
will be in blocking mode


a) why, when “this” is used as lock token, isn’t the whole object
locked, and not just methods with locks inside them?

Wouldn’t it be more safe, since some other thread may be using some
other means to access and operate on same members of A1 as A1.A_m1()
is, and thus data may become corrupted?

The only effect by locking an object is that another object
can not lock on the object (not quite true - there are also some
memory model effects, but let us ignore them for simplicity).

The lock does not have any impact in any way on code not
trying to lock on the same object.

Therefore it is essential that the various code agree on what
to lock on.
2) Book suggests that if you are locking down a region of code within
apublic member, it is safer to declare a private object member
variable to serve as a token:

class Printer
{
private object threadLock = new object();
public void PrintNumbers()
{
lock ( threadLock )
{ …}
}
}


Now why would having a public token in a public method represent a
security risk:

class Printer
{
public void PrintNumbers()
{
lock ( this )
{

}
}
}

My take on this is that this locking used is an internal thing
and should not lock on something that is external.

The traditional explanation is that by using this then locking
could become a mess and potentially lead to deadlocks.

But since the private lock object is not an option in all
cases, then it is not a general solution.

Arne
 
G

Göran Andersson

I thought it does in cases where object used for locking is also
object the code inside the lock statement is operating on

No, that only means that you have chosen to use the same object for
locking as the one that you are protecting.
What would be the best way to protect that data? If you pass some
object O of type T into a method, then only way you can protect O
( while code in a method is operating on it), is that you somehow make
sure there is no other method ( defined in this or any other class )
operating on that data at the same time.?!
Now since you can’t lock O, I’m not sure how you would manage to
protect it ( assuming some third party created type T and also
assuming app also has some third-party objects that also can operate
on O )?!

One way to protect data is to use immutable objects. If you for example
send a string (which is immutable) into a method, you can be sure that
the string will not change while the method is running.

Another way to protect data is to make a copy of it before you enter the
lock.
 
B

beginwithl

Hi

May I also ask the following:

Say we have 10 threads and each thread wants to pass an object to
method A_m1 (in class A1) with lock inside in order to do some
operations on them. Now if we use as a token some single private
object declared in A1, then we can only operate on one object at the
time. Instead we could declare inside A1 an array of private objects,
and then use these objects as tokens – this way, none of the threads
would block and thus 10 “instances” of A_m1 could be operating at the
“same” time. Would that be considered a good design?

That's exactly what I meant.

*I’m sorry, I should have check it myself rather than asking you guys,
but I was so sure that if two different methods lock on same object,
then no blocking would occur since I assumed that Monitor.Enter()
distinguishes between the two situations - first situation being
where two different methods lock on same object ( at the same time )
and second one where two calls to same method lock the same object (at
the same time).

*Would it be any less safer if it was allowed for different methods to
lock the same object ( at the same time ) without being blocked?


*If we were to nitpick, we could argue that it is actually the code
inside the lock statement, that is ”locked”, and not the method which
contains this lock statement?!

*So it’s not best practice to use as a token an object on which we
also want the method to operate on. I know I’m repeating myself, but
if the object used as a token was actually locked ( I realize it
isn’t ), then things would be greatly simplified and there would be
far less chances for data corruption. But now, you have to somehow
synchronize all the different methods that may be operating on the
same data ( and it gets even more complicated since one should only
use private (thus internal) objects ).


BTW - Are nested locks considered a bad design?


Much appreciated
 
G

Göran Andersson

Hi

May I also ask the following:

Say we have 10 threads and each thread wants to pass an object to
method A_m1 (in class A1) with lock inside in order to do some
operations on them. Now if we use as a token some single private
object declared in A1, then we can only operate on one object at the
time. Instead we could declare inside A1 an array of private objects,
and then use these objects as tokens – this way, none of the threads
would block and thus 10 “instances” of A_m1 could be operating at the
“same” time. Would that be considered a good design?

Then you would have to identify the threads in some way to choose a sync
object to use with the thread.

Normally each thread would use their own instance of the A1 class.
*Would it be any less safer if it was allowed for different methods to
lock the same object ( at the same time ) without being blocked?

That would make it impossible to implement protection for classes where
different methods are needed to access the same data.
*If we were to nitpick, we could argue that it is actually the code
inside the lock statement, that is ”locked”, and not the method which
contains this lock statement?!

Yes, that's what I have been saying all along.
*So it’s not best practice to use as a token an object on which we
also want the method to operate on. I know I’m repeating myself, but
if the object used as a token was actually locked ( I realize it
isn’t ), then things would be greatly simplified and there would be
far less chances for data corruption.

Yes, that would be a lot simpler. It's a pity that it's not practically
possible. It could be implemented for managed code, but that would cause
something like a 10000% overhead on every memory access...
But now, you have to somehow
synchronize all the different methods that may be operating on the
same data ( and it gets even more complicated since one should only
use private (thus internal) objects ).

Yes, thread safety is not that easy to implement. It requires that you
think in a completely different way from regular linear programming, and
it's hard to verify that the code is truely thread safe.
BTW - Are nested locks considered a bad design?

No, but you should be restrictive to use that and careful when
implementing it, as that's where deadlocks can occur.
 
P

Peter Morris

Easier way to think of it is this

01: The code within the { } is what is locked
02: The object within the ( ) is the key to lock/unlock it, and only 1 piece
of code can use that key at once.

lock (thisIsTheKey)
{
//Nobody else can use that key yet
//Not yet either
}
//Now they can


So be aware that you could do

Thread 1:
lock (thisIsTheKey)
{
X++;
X++;
}

Thread 2:
lock (thisIsTheWrongKey)
{
//Same state is being modified, you should use the same key
X++;
X++;
}

This is perfectly valid in some circumstances (e.g. if one was using Y
instead of X), just in this example completely wrong :)
 
B

beginwithl

hi


Then you would have to identify the threads in some way to choose a sync
object to use with the thread.
Normally each thread would use their own instance of the A1 class.

In that case A1 could have just one private object defined ( for the
purpose of being a token ) instead of having an array of private
objects?!


Thanx guys, I really appreciate it
 
G

Göran Andersson

In that case A1 could have just one private object defined ( for the
purpose of being a token ) instead of having an array of private
objects?!

Yes, that is correct.
 
B

beginwithl

Hi


I will wrap this up, but the following is still bugging me a bit:

Say we have class A. Now I know you guys said that only private
objects should be used for locks.
But if that is the case, then if we want to operate on data members of
class A, then the only way to ensure synchronized access to data
members of A is by only allowing methods ( using locks inside of
them ) of class A to operate on these data members ( thus no outside
methods can perform any operations on critical data, not even via
properties of class A )

But doesn’t that severely limit the usefulness of a class? Thus, do
benefits really outweigh the risk?

cheers
 
B

beginwithl

hi

As far as properties go, a property is _not_ a data member. It's a pair
of methods used to get or set a data member, and if you want a property to
be thread-safe, it's simple enough to include the same synchronization
mechanism that you'd include elsewhere in the class.

Yes, I know what properties are, and only reason I can think of for
making such a question is due to sudden brain fart ( I know I've been
having a lot of those lately )


again, I really appreciate all of your kind help

cheers
 

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