我開始研究lock,馬上就出現了一個問題。
docs.microsoft在這里說:
lock 陳述句獲取給定物件的互斥鎖,執行陳述句塊,然后釋放鎖。持有鎖時,持有鎖的執行緒可以再次獲取和釋放鎖。任何其他執行緒都被阻止獲取鎖并等待直到鎖被釋放。
我做了一個簡單的例子,證明另一個執行緒使用不帶 lock 關鍵字的方法可以輕松更改實體的資料,而該實體被使用第一個執行緒的鎖的方法占用。值得從阻塞中洗掉評論,并且作業按預期完成。我認為鎖會阻止其他執行緒對實體的訪問,即使他們沒有在他們的方法中對該實體使用鎖。
問題:
我是否正確理解在一個執行緒上鎖定實體允許在該實體上修改來自另一個執行緒的資料,除非另一個執行緒也使用該實體的鎖?如果是這樣,那么這種阻塞通常會帶來什么?為什么要這樣做?
用更簡單的術語來說這意味著什么?持有鎖時,持有鎖的執行緒可以再次獲取和釋放鎖。
所以代碼格式化效果很好。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class A
{
public int a;
}
class Program
{
static void Main(string[] args)
{
A myA = new A();
void MyMethod1()
{
lock (myA)
{
for (int i = 0; i < 10; i )
{
Thread.Sleep(500);
myA.a = 1;
Console.WriteLine($"Work MyMethod1 a = {myA.a}");
}
}
}
void MyMethod2()
{
//lock (myA)
{
for (int i = 0; i < 10; i )
{
Thread.Sleep(500);
myA.a = 100;
Console.WriteLine($"Work MyMethod2 a = {myA.a}");
}
}
}
Task t1 = Task.Run(MyMethod1);
Thread.Sleep(100);
Task t2 = Task.Run(MyMethod2);
Task.WaitAll(t1, t2);
}
}
}
uj5u.com熱心網友回復:
鎖是合作的,它依賴于可以更改資料的各方合作并在嘗試更改資料之前獲取鎖。請注意,鎖并不關心您在鎖內更改的內容。在保護某些資料結構時,使用代理鎖物件是相當普遍的。IE
private object myLockObject = new object();
private int a;
private int b;
public void TransferMonety(int amount){
lock(myLockObject){
if(a > amount){
a-=amount;
b =amount;
}
}
}
因為這個鎖非常靈活,你可以保護任何一種操作,但是你需要正確地撰寫你的代碼。
因此,在使用鎖時要小心謹慎。鎖最好是私有的,以避免任何不相關的代碼獲取鎖。鎖內的代碼應該相當短,并且不應該呼叫類外的任何代碼。這樣做是為了避免死鎖,如果運行任意代碼,它可能會執行諸如獲取其他鎖或等待事件之類的事情。
雖然鎖非常有用,但根據您的用例,還可以使用其他同步原語。
uj5u.com熱心網友回復:
用更簡單的術語來說這意味著什么?“當持有鎖時,持有鎖的執行緒可以再次獲取和釋放鎖。”
這意味著您可以這樣做:
lock (locker)
{
lock (locker)
{
lock (locker)
{
// Do something while holding the lock
}
}
}
您可以多次獲取鎖,然后釋放相同次數的鎖。這稱為重入。該lock陳述句是可重入的,因為基礎Monitor類在設計上是可重入的。其他同步原語,如SemaphoreSlim,是不可重入的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/423035.html
標籤:
