about using the Lock synchorization mechanism

T

Tony Johansson

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();
}
}
 
P

Peter Duniho

Tony said:
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
 
T

Tony Johansson

Peter Duniho said:
Tony said:
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
 
A

Arne Vajhøj

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
 
P

Peter Duniho

Tony said:
[...]
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
 
T

Tony Johansson

Good Expained Arne!!

//Tony


Arne Vajhøj said:
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
 

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