Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Příkaz lock získá zámek vzájemného vyloučení pro daný objekt, spustí blok příkazu a pak uvolní zámek. Zatímco se zámek drží, vlákno, které zámek obsahuje, může zámek znovu získat a uvolnit. Jakékoli jiné vlákno se zablokuje v získání zámku a počká, až se zámek uvolní. Tento lock příkaz zajistí, že v libovolném okamžiku spustí tělo maximálně jednoho vlákna.
Příkaz lock má následující formu:
lock (x)
{
// Your code...
}
Proměnná x je výraz typu System.Threading.Lock nebo odkazový typ. Pokud x je známo, že v době kompilace má být typ System.Threading.Lock, je přesně ekvivalentní:
using (x.EnterScope())
{
// Your code...
}
Objekt vrácený Lock.EnterScope() je objekt ref struct , který zahrnuje metodu Dispose() . Vygenerovaný using příkaz zajistí uvolnění oboru i v případě, že je vyvolán výjimka s tělem lock příkazu.
lock V opačném případě je příkaz přesně ekvivalentní:
object __lockObj = x;
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
// Your code...
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}
Vzhledem k tomu, že kód používá try-finally příkaz, zámek se uvolní i v případě, že je v těle lock příkazu vyvolán výjimka.
Výraz nelze použít await v textu lock příkazu.
Pokyny
Počínaje rozhraním .NET 9 a C# 13 zamkněte vyhrazenou instanci objektu System.Threading.Lock typu pro zajištění nejlepšího výkonu. Kromě toho kompilátor vydá upozornění, pokud je známý Lock objekt přetypován na jiný typ a uzamčen. Pokud používáte starší verzi .NET a C#, zamkněte vyhrazenou instanci objektu, která se nepoužívá k jinému účelu. Nepoužívejte stejnou instanci objektu uzamčení pro různé sdílené prostředky, protože může vést k zablokování nebo kolizí uzamčení. Zejména nepoužívejte následující instance jako objekty zámků:
-
this, protože volající mohou také uzamknoutthis. - Type instance, protože mohou být získány typeof operátor nebo reflexe.
- instance řetězců, včetně řetězcových literálů, protože se můžou prolínat.
Držte zámek co nejkratší dobu, abyste snížili kolize zámků.
Příklad
Následující příklad definuje Account třídu, která synchronizuje přístup k jeho privátnímu balance poli uzamčením vyhrazené balanceLock instance. Použití stejné instance pro uzamčení zajišťuje, že dvě různá vlákna nemohou aktualizovat balance pole voláním Debit nebo Credit metod současně. Ukázka používá C# 13 a nový Lock objekt. Pokud používáte starší verzi jazyka C# nebo starší knihovnu .NET, zamkněte instanci object.
using System;
using System.Threading.Tasks;
public class Account
{
// Use `object` in versions earlier than C# 13
private readonly System.Threading.Lock _balanceLock = new();
private decimal _balance;
public Account(decimal initialBalance) => _balance = initialBalance;
public decimal Debit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The debit amount cannot be negative.");
}
decimal appliedAmount = 0;
lock (_balanceLock)
{
if (_balance >= amount)
{
_balance -= amount;
appliedAmount = amount;
}
}
return appliedAmount;
}
public void Credit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The credit amount cannot be negative.");
}
lock (_balanceLock)
{
_balance += amount;
}
}
public decimal GetBalance()
{
lock (_balanceLock)
{
return _balance;
}
}
}
class AccountTest
{
static async Task Main()
{
var account = new Account(1000);
var tasks = new Task[100];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() => Update(account));
}
await Task.WhenAll(tasks);
Console.WriteLine($"Account's balance is {account.GetBalance()}");
// Output:
// Account's balance is 2000
}
static void Update(Account account)
{
decimal[] amounts = [0, 2, -3, 6, -2, -1, 8, -5, 11, -6];
foreach (var amount in amounts)
{
if (amount >= 0)
{
account.Credit(amount);
}
else
{
account.Debit(Math.Abs(amount));
}
}
}
}
Specifikace jazyka C#
Další informace naleznete v části Příkaz lockspecifikace jazyka C#.