Safer locking support

G

Guest

Using lock(this) has been much maligned since someone external to your object
can lock causing possible deadlock and forcing you to now create an extra
object lock_=new object(); in any classes using locking with nothing better
to lock on.

How about supporting a protected property on System.Object as SyncObj (so it
is really an internal locking object rather than this object) or something
like that that can be locked on. Perhaps the C# can be changed to support
the following:

lock
{
//...

}

With no arguments to lock it would by default use the protected SyncObj.
This will make C#.NET threading safer and easier.
 
M

Mattias Sjögren

How about supporting a protected property on System.Object as SyncObj (so it
is really an internal locking object rather than this object) or something
like that that can be locked on.

I assume that would be an instance member then, since otherwise all
classes would lock on the same object. If it's an instance member,
every object now has to pay the cost of an extra object reference even
if you don't need any locking support. What a waste.

I don't see why this would be any better than what we do today with
explicitly declaring the object to lock on.


Mattias
 
J

Jon Skeet [C# MVP]

WXS said:
Using lock(this) has been much maligned since someone external to your object
can lock causing possible deadlock and forcing you to now create an extra
object lock_=new object(); in any classes using locking with nothing better
to lock on.

How about supporting a protected property on System.Object as SyncObj (so it
is really an internal locking object rather than this object) or something
like that that can be locked on. Perhaps the C# can be changed to support
the following:

lock
{
//...

}

With no arguments to lock it would by default use the protected SyncObj.
This will make C#.NET threading safer and easier.

Hmmm... not entirely sure. I prefer the idea of specifying a lock
explicitly, as per
http://www.pobox.com/~skeet/csharp/miscutil/usage/locking.html

If SyncObj in your scheme were to default to a new object, that would
mean that *every* object would have to have an extra field, which is an
unacceptably high cost IMO, considering that most types don't need
locking.
 
G

Guest

As a protected instance member this means you don't need to explicitly
declare a object to lock on. Probably also a good idea for the compiler to
generate a warning if lock(this) is used, since it really isn't safe (though
that may be a bit much). Certainly less typing with this method, possibly
prevents the need to internally allocate a new real object to lock on if the
internal mechanism is used. There is likely overhead in a base object you
just don't need if really you just want a lock. It also likely opens up some
compiler and JIT optimizations that would have been difficult before, as now
you know specifically what is being locked where before it had to be
interpreted at runtime.

Just some thoughts...
 
G

Guest

Right, but it could use the same delayed allocation scheme as the existing
locks.

Explicit definition forces me to allocate quite often a useless object to
lock on:
object uselessLocker_=new object();
Just so I can lock on it. Perhaps SyncObj doesn't need to be an object at
all, and the

lock
{
}

Construct could possible be optimized out the need to have an actual object
creation just to lock on.
 
G

Guest

Actually another quick thought on this is it may be possible to avoid having
to dynamically create a lock object at all and implementation could be
handled at compile time since the compiler could know if a lock was needed
just by examining the class. (There might be some cases it can't possible,
abstract virtual methods I haven't thought through completely.. but I
certainly think there are some interesting optimizations available to this
method).
 
J

Jon Skeet [C# MVP]

WXS said:
Right, but it could use the same delayed allocation scheme as the existing
locks.

It's not so much the allocation that worries me (although in order to
delay the allocation but still do it in a thread-safe manner you'd need
to be able to lock on something else).

However, what *does* worry me is that you'd need a reference field in
the first place. You've just added 4 bytes to *every single object in
the system* - or 8 bytes on an x64 system. I'd far rather have a bit of
overhead on everything that explicitly declares and creates a lock
object (which shouldn't be that many types) than take an extra 4 or 8
bytes for every object in the system.
Explicit definition forces me to allocate quite often a useless object to
lock on:
object uselessLocker_=new object();
Just so I can lock on it. Perhaps SyncObj doesn't need to be an object at
all, and the

lock
{
}

Construct could possible be optimized out the need to have an actual object
creation just to lock on.

So what would it lock on, and how would you share that between
different threads?
 
J

Jon Skeet [C# MVP]

WXS said:
Actually another quick thought on this is it may be possible to avoid having
to dynamically create a lock object at all and implementation could be
handled at compile time since the compiler could know if a lock was needed
just by examining the class. (There might be some cases it can't possible,
abstract virtual methods I haven't thought through completely.. but I
certainly think there are some interesting optimizations available to this
method).

At this point, things are definitely looking significantly more
complicated than using an explicit locking class, and you don't get the
benefits such as timeouts, ordering for deadlock detection etc.

There's virtue in simplicity :)
 
M

Mattias Sjögren

As a protected instance member this means you don't need to explicitly
declare a object to lock on. Probably also a good idea for the compiler to
generate a warning if lock(this) is used, since it really isn't safe (though
that may be a bit much). Certainly less typing with this method, possibly
prevents the need to internally allocate a new real object to lock on if the
internal mechanism is used. There is likely overhead in a base object you
just don't need if really you just want a lock. It also likely opens up some
compiler and JIT optimizations that would have been difficult before, as now
you know specifically what is being locked where before it had to be
interpreted at runtime.

Your reasoning has a lot of "probably", "possibly" and "likely" in it.
Suffice to say I'm not convinced.

Based on your other posts in this thread (about lock {} with no object
specified) you also seem to think that all code sections sharing a
lock are within the same class, and that all methods in a class that
need locking are to lock on the same object. Now that's a very
simplified view and often not true.


Mattias
 
G

Guest

I think that overhead could be avoided to only be added if in fact it was
needed if it was a compile time optimization. For runtime I would agree
accept for the fact they already do this for system.object. Perhaps you could
attribute your object to avoid the internal requirement for the existing one
so it could re-use that space. I see your point though.
 
G

Guest

I agree with the simplicity case I just think it would be the simplest for
most users. I also agree it is missing the benefits you mentioned, the
reality is though most users don't do that... they just do lock(this), and
incur the issues related to that.

Coming up with language definitions is hard :) There are always many sides
and concerns to a problem.. which I guess is why it takes years...
 
J

Jon Skeet [C# MVP]

WXS said:
I agree with the simplicity case I just think it would be the simplest for
most users. I also agree it is missing the benefits you mentioned, the
reality is though most users don't do that... they just do lock(this), and
incur the issues related to that.

Making it harder to understand what's going on under the hood won't
help this.
Coming up with language definitions is hard :) There are always many sides
and concerns to a problem.. which I guess is why it takes years...

Sure - I just can't see this suggestion going anywhere, I'm afraid.
 

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