问题
I'm working on a class that creates and manages multiple socket connections and which will be forwarding information received from the sockets to the main thread and vice-versa. Multi-threading where I'm passing so much information in and out is new to me (as is most things in C#), so I need a clarification on what exactly locks
do.
When I lock a section of a method does it only ensure that no other thread can enter that section of code or does it actually prevent all the variables in that section of code from being modified by other threads no matter where they occur?
For example:
public class TestLock
{
public volatile int a = 0;
public volatile int b = 2;
private object ALock = new Object();
public TestLock() { }
public void UnlockEdit(int atemp, int btemp)
{
a = atemp;
b = btemp;
}
public void LockedEdit(int atemp, int btemp)
{
lock(ALock)
{
a = atemp;
b = btemp;
}
}
public int[] ReturnValues()
{
int[] ret = new int[2];
lock (ALock)
{
ret[0] = a;
ret[1] = b;
}
return ret;
}
}
If thread A calls the LockedEdit
method and reaches the lock just slightly before thread B comes into UnlockEdit
. What happens? Will the lock prevent thread B from modifying a
and b
? And will it block? Or does the lock only apply to the one particular branch of code? Or should I apply the same lock
object (ALock
) to every single read and write method for the objects I want to modify and read from multiple threads?
回答1:
The lock statement creates a critical section in your code. This prevents other threads from entering the code inside the lock statements brackets. Other threads basically wait until it is their turn to enter the section.
It does not prevent other threads from modifying variables in the class. For instance, TestLock.a and TestLock.b could be modified by a function inside the TestLock class that does not use the Lock(ALock) statement. ALso, since variables a and b are public they could be modified by code outside the class (on a separate thread).
Here is a good link to .NET Basic Threading:
FROM MSDN:
The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released.
Here is an example of some code that keeps variables safe for multithreaded applications (Taken from the C# 3.0 cookbook):
public static class SaferMemberAccess
{
private static int numericField = 1;
private static object syncObj = new object( );
public static void IncrementNumericField( )
{
lock(syncObj)
{
++numericField;
}
}
public static void ModifyNumericField(int newValue)
{
lock(syncObj)
{
numericField = newValue;
}
}
public static int ReadNumericField( )
{
lock (syncObj)
{
return (numericField);
}
}
}
回答2:
When I lock a section of a method does it only ensure that no other thread can enter that section of code or does it actually prevent all the variables in that section of code from being modified by other threads no matter where they occur?
This question is so complicated and ill-formed that it is impossible to answer. Let's rewrite it.
When I lock a section of a method does it ensure that no other thread can enter that section of code?
Yes. A more accurate way to state that however is to say: the locked section cannot be entered until the lock associated with the "monitor" object given to the lock
statement is obtained. That lock may only be obtained by one thread at a time.
I note also that there are subtleties about how locks may be obtained in scenarios involving more advanced usages of the monitor, such as pulsing. Again, read the documentation carefully for a description of the exact semantics of the operations of a monitor.
When I lock a section of a method does it only ensure that no other thread can enter that section of code?
No. Taking a lock has other actions than merely ensuring mutual exclusion on a block. It introduces a memory barrier, for example.
does it actually prevent all the variables in that section of code from being modified by other threads no matter where they occur?
Certainly not!
Will the lock prevent thread B from modifying a and b?
You build a bathroom with a door with a lock on one side and one side open to the outside world. You lock the bathroom door. Does that seem like an effective way to ensure that only one person can squeeze the toothpaste at a time?
And will it block?
Will what block?
does the lock only apply to the one particular branch of code?
I can't make sense of this question.
should I apply the same "lock" object (ALock) to every single read and write method for the objects I want to modify and read from multiple threads?
Yes.
A question you did not ask but should have:
Should I be using shared-memory multithreading in the first place?
Probably not. It is extremely difficult even for experts to get it right. Were I doing socket programming I'd start by using async-await or the Task Parallel Library to manage my asynchrony, rather than partying on threads directly. Threads are a very low-level tool intended for experts; try to raise the level of abstraction several levels.
回答3:
You acquire a lock on the object as you did here
lock(ALock)
this section of the code is now locked by this object and no other object can get in until the lock is freed, i.e this object leaves the critical section.
It also means that in this time no other object will be able to modify the variables locked by this object in the critical section.
来源:https://stackoverflow.com/questions/21544823/what-precisely-does-a-lock-lock