From: Tony Johansson on
Hi!

At the bottom I have a class named Counter and in a method called
UpdateCount I use this statement
lock(this) to synchronize so that only one thread can access this section of
code. In class Test is main located also listed at the end.

I made a test to access method Foo in this class Counter using the same
object as I do when calling method UpdateCount
and it worked. First I was a litle uncertain if this statement lock(this)
will lock the object this in any way but it doesn't.

So accoding to my test this argument that is passed to lock here this which
is the currect Counter object is not locking
this Counter object in any way.

So what purpose has this argument that is passed to lock actually if it
doesn't lock the current object which I first thought..?


using System;
using System.Threading;

class Counter
{
private int _count;
private int _evenCount;

public int Count
{ get { return _count; } }

public int EvenCount
{ get { return _evenCount; } }

public void Foo()
{
System.Diagnostics.Trace.WriteLine("Before In Foo");
_count = 0;
System.Diagnostics.Trace.WriteLine("After In Foo");
}

public void UpdateCount()
{
lock(this)
{
_count = _count +1;
if (Count % 2 == 0)
_evenCount = _evenCount;
}
}
}

class Test
{
public static void Main()
{
Counter count = new Counter();
ParameterizedThreadStart starter = new
ParameterizedThreadStart(UpdateCount);
Thread[] threads = new Thread[10];

for (int x = 0; x < 10; x++)
{
threads[x] = new Thread(starter);
threads[x].Start(count);
}

for (int x = 0; x < 10; x++)
{
if (x == 0)
{
ParameterizedThreadStart starter2 = new
ParameterizedThreadStart(Foo);
Thread th = new Thread(starter2);
th.Start(count);
}
threads[x].Join();
}
Console.WriteLine("Total: {0} - EvenCount: {1}", count.Count,
count.EvenCount);
}

static void UpdateCount(object param)
{
Counter count = (Counter)param;
for (int x= 1; x <= 10000; x++)
count.UpdateCount();
}

static void Foo(object param)
{
Counter count = (Counter)param;
count.Foo();
}
}


From: Peter Duniho on
Tony Johansson wrote:
> Hi!
>
> At the bottom I have a class named Counter and in a method called
> UpdateCount I use this statement
> lock(this) to synchronize so that only one thread can access this section of
> code. In class Test is main located also listed at the end.
>
> I made a test to access method Foo in this class Counter using the same
> object as I do when calling method UpdateCount
> and it worked. First I was a litle uncertain if this statement lock(this)
> will lock the object this in any way but it doesn't.
>
> So accoding to my test this argument that is passed to lock here this which
> is the currect Counter object is not locking
> this Counter object in any way.
>
> So what purpose has this argument that is passed to lock actually if it
> doesn't lock the current object which I first thought..? [...]

The "lock" statement only synchronizes the block of code within the
"lock" statement's block with the same block of code or another block of
code using a "lock" statement with the same target used in the first
"lock" statement.

It is not a good idea to use "this" as the target of the "lock"
statement in any case, but here it appears to be confusing you into
thinking that the entire object somehow gets locked by virtue of using
it as the target. That's not how "lock" works.

Pete
From: Tony Johansson on
"Peter Duniho" <no.peted.spam(a)no.nwlink.spam.com> skrev i meddelandet
news:em30tdF8KHA.5476(a)TK2MSFTNGP06.phx.gbl...
> Tony Johansson wrote:
>> Hi!
>>
>> At the bottom I have a class named Counter and in a method called
>> UpdateCount I use this statement
>> lock(this) to synchronize so that only one thread can access this section
>> of code. In class Test is main located also listed at the end.
>>
>> I made a test to access method Foo in this class Counter using the same
>> object as I do when calling method UpdateCount
>> and it worked. First I was a litle uncertain if this statement lock(this)
>> will lock the object this in any way but it doesn't.
>>
>> So accoding to my test this argument that is passed to lock here this
>> which is the currect Counter object is not locking
>> this Counter object in any way.
>>
>> So what purpose has this argument that is passed to lock actually if it
>> doesn't lock the current object which I first thought..? [...]
>
> The "lock" statement only synchronizes the block of code within the "lock"
> statement's block with the same block of code or another block of code
> using a "lock" statement with the same target used in the first "lock"
> statement.
>
> It is not a good idea to use "this" as the target of the "lock" statement
> in any case, but here it appears to be confusing you into thinking that
> the entire object somehow gets locked by virtue of using it as the target.
> That's not how "lock" works.
>
> Pete

What do you mean here ?
The "lock" statement only synchronizes the block of code within the
"lock" statement's block with the same block of code or another block of
code using a "lock" statement with the same target used in the first
"lock" statement.

//Tony


From: Arne Vajhøj on
On 10-05-2010 09:14, Tony Johansson wrote:
> At the bottom I have a class named Counter and in a method called
> UpdateCount I use this statement
> lock(this) to synchronize so that only one thread can access this section of
> code. In class Test is main located also listed at the end.
>
> I made a test to access method Foo in this class Counter using the same
> object as I do when calling method UpdateCount
> and it worked. First I was a litle uncertain if this statement lock(this)
> will lock the object this in any way but it doesn't.
>
> So accoding to my test this argument that is passed to lock here this which
> is the currect Counter object is not locking
> this Counter object in any way.
>
> So what purpose has this argument that is passed to lock actually if it
> doesn't lock the current object which I first thought..?

lock is a cooperative locking mechanism not an enforcing locking
mechanism.

Think of:

lock(obj) {
...
}

as:

obj.WaitUntilLockFlagNotSetAndThenSetLockFlag();
....
obj.UnsetLockFlag();

It does not put obj in a state where other code can
not use it.

It only synchronizes with other code that also uses
the lock flag of the object.

This is possible:

thread #1 thread #2

lock(obj) {
obj.foo(); obj.bar();
}

This is not possible:

thread #1 thread #2

lock(obj) { lock(obj) {
obj.foo(); obj.bar();
} }

so it will become either:

thread #1 thread #2

lock(obj) {
obj.foo();
}
lock(obj) {
obj.foo();
}

or:

thread #1 thread #2

lock(obj) {
obj.foo();
}
lock(obj) {
obj.foo();
}

Arne
From: Peter Duniho on
Tony Johansson wrote:
> [...]
> What do you mean here ?
> The "lock" statement only synchronizes the block of code within the
> "lock" statement's block with the same block of code or another block of
> code using a "lock" statement with the same target used in the first
> "lock" statement.

I mean what it says. Which words are you having trouble understanding,
specifically?

I thought what I wrote was clear. But if not, perhaps you would prefer
just reading the documentation:
http://msdn.microsoft.com/en-us/library/c5kehkcz(v=VS.100).aspx

Pete