What is the best way to do thread locking in .NET?Thanks

L

linuxfedora

if i have a Queue named testQ

Object lockQ = new Object();

testQ will be modified by:

void AddToQueue(string text)
{
lock(lockQ )
{
testQ.Enqueue(text);
}
}

string RemoveFromQueue()
{
lock(lockQ )
{
string text = (string)testQ.Dequeue();
}
return text ;
}

void PrintInfo()
{
lock(lockQ)
{
for(int i=0;i<testQ.Count;i++)
{
Console.WriteLine("String=" + RemoveFromQueue());
}
}
}

How to ensure that the PrintInfo is not affected if when it is
printing the info, a new text is added to the Queue in AddToQueue
function? And the most effective way to do it is?Thanks
 
G

Guest

if i have a Queue named testQ

Object lockQ = new Object();

testQ will be modified by:

void AddToQueue(string text)
{
lock(lockQ )
{
testQ.Enqueue(text);
}
}

string RemoveFromQueue()
{
lock(lockQ )
{
string text = (string)testQ.Dequeue();
}
return text ;
}

void PrintInfo()
{
lock(lockQ)
{
for(int i=0;i<testQ.Count;i++)
{
Console.WriteLine("String=" + RemoveFromQueue());
}
}
}

How to ensure that the PrintInfo is not affected if when it is
printing the info, a new text is added to the Queue in AddToQueue
function? And the most effective way to do it is?Thanks

You are pretty close. You have to declare the text variable outside the
scope of the lock to be able to return it:

string RemoveFromQueue() {
string text;
lock(lockQ ) {
text = (string)testQ.Dequeue();
}
return text;
}

You don't have to call RemoveFromQueue in the PrintInfo method, you can
use testQ.Dequeue as it's protected inside the lock block.

You can't use testQ.Count that way in the loop, though. As both i and
testQ.Count are changing in the loop you will only show half of the
items. Just loop as long as there are items in the queue:

void PrintInfo() {
lock(lockQ) {
while (testQ.Count > 0) {
Console.WriteLine("String=" + (string)testQ.Dequeue());
}
}
}

I would suggest that you put these methods, the testQ variable and the
lock variable in a class by themselves, so that the queue and the lock
variable are isolated from the rest of the code. That way the queue
can't be manipulated by any other code by mistake.
 
L

linuxfedora

You are pretty close. You have to declare the text variable outside the
scope of the lock to be able to return it:

string RemoveFromQueue() {
string text;
lock(lockQ ) {
text = (string)testQ.Dequeue();
}
return text;

}

You don't have to call RemoveFromQueue in the PrintInfo method, you can
use testQ.Dequeue as it's protected inside the lock block.

You can't use testQ.Count that way in the loop, though. As both i and
testQ.Count are changing in the loop you will only show half of the
items. Just loop as long as there are items in the queue:

void PrintInfo() {
lock(lockQ) {
while (testQ.Count > 0) {
Console.WriteLine("String=" + (string)testQ.Dequeue());
}
}

}

I would suggest that you put these methods, the testQ variable and the
lock variable in a class by themselves, so that the queue and the lock
variable are isolated from the rest of the code. That way the queue
can't be manipulated by any other code by mistake.

--
Göran Andersson
_____http://www.guffa.com- -

- -

Thanks.
 
J

Jon Skeet [C# MVP]

G?ran Andersson said:
You are pretty close. You have to declare the text variable outside the
scope of the lock to be able to return it:

string RemoveFromQueue() {
string text;
lock(lockQ ) {
text = (string)testQ.Dequeue();
}
return text;
}

Not really - I'd say it would be cleaner to return it directly from
inside the lock:

string RemoveFromQueue()
{
lock (lockQ)
{
return (string) testQ.Dequeue();
}
}

This will still release the lock appropriately.

<snip>
 
L

linuxfedora

How about:
There are 2 threads, named thread1 and thread2, they will also access
the method in test1 named testMethod as below:

thread1 will call testMethod(10);
thread2 will call testMethod(20);

public void testMethod(int count)
{
lock(lockData)
{
for(int i=0;i<count;i++)
{
Console.WriteLine("i=" + i);
}
}
}
}

is that possible to lock the count varaible? because the function
parameter is not in the LOCK?Thanks
 
P

Peter Duniho

[...]
is that possible to lock the count varaible? because the function
parameter is not in the LOCK?Thanks

There is no need to lock the count variable, since each thread has its
own instance of the variable. The variable isn't shared between threads.

Pete
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Peter said:
[...]
is that possible to lock the count varaible? because the function
parameter is not in the LOCK?Thanks

There is no need to lock the count variable, since each thread has its
own instance of the variable. The variable isn't shared between threads.

Pete

Also:

You don't lock the object, you lock the code. The lock prevents another
thread to enter a code block that is locked on the same object. The
object that you use in the lock statement is just an identifier for the
lock, it doesn't protect the object.

You can't use a value type in a lock statement. The value would be boxed
in a new object, so another lock on the same value would lock on a
separate new object.
 
J

Jon Skeet [C# MVP]

Göran Andersson said:
Also:

You don't lock the object, you lock the code. The lock prevents another
thread to enter a code block that is locked on the same object. The
object that you use in the lock statement is just an identifier for the
lock, it doesn't protect the object.

While I see your point, I'd say you lock the *reference* rather than
either the object or the code.

In particular, the phrase "lock the code" (without reading the rest of
the text) would suggest that no other thread can execute the same code
at the same time. It can, if it ends up locking on a different
reference.

The explanation is spot on, of course.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Jon said:
While I see your point, I'd say you lock the *reference* rather than
either the object or the code.

In particular, the phrase "lock the code" (without reading the rest of
the text) would suggest that no other thread can execute the same code
at the same time. It can, if it ends up locking on a different
reference.

I see what you mean. I'd say that it doesn't lock the reference either,
it just locks the lock. :)
The explanation is spot on, of course.

Thanks. :)
 
P

Peter Duniho

Göran Andersson said:
Jon said:
Göran Andersson said:
Also:

You don't lock the object, you lock the code. [...]

While I see your point, I'd say you lock the *reference* rather than
either the object or the code.

[...]

I see what you mean. I'd say that it doesn't lock the reference either,
it just locks the lock. :)

I think what you call it is not nearly so important as understanding
that like a critical section or other synchronization mechanism, it only
protects data when all code that accesses the data cooperates and uses
the same mechanism.

Code isn't locked, the object isn't locked, nothing is literally locked.
What does happen is that the synchronization mechanism in use ensures
only a single thread at a time has access to the resource.

Without cooperation between all of the relevant code, this doesn't happen.

IMHO, your original elaboration made this point reasonably well. :)
There's probably no need to worry about whether we are saying that the
variable is locked or the code is locked or the object is locked or
the... :)

Pete
 

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