lock deyimi - Paylaşılan kaynağa özel erişim sağlayın.

deyimi, lock belirli bir nesne için karşılıklı dışlama kilidini alır, bir deyim bloğu yürütür ve sonra kilidi serbest bırakır. Kilit tutulurken, kilidi tutan iş parçacığı kilidi yeniden alabilir ve serbest bırakabilir. Diğer iş parçacıklarının kilidi almaları engellenir ve kilit serbest bırakılana kadar bekler. deyimi, lock tek bir iş parçacığının bu nesneye özel erişime sahip olmasını sağlar.

deyimi lock formun

lock (x)
{
    // Your code...
}

burada x bir başvuru türünün ifadesidir. Bu, tam olarak

object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

Kod bir try kullandığından ... finally block, bir deyiminin gövdesinde lock bir özel durum oluşturulduğunda bile kilit serbest bırakılır.

Bir deyiminin gövdesinde await işlecinilock kullanamazsınız.

Yönergeler

Paylaşılan bir kaynağa iş parçacığı erişimini eşitlerken, ayrılmış bir nesne örneğine (örneğin) private readonly object balanceLock = new object();veya kodun ilişkisiz bölümleri tarafından kilit nesnesi olarak kullanılma olasılığı düşük olan başka bir örneğe kilitleyin. Kilitlenme veya kilit çekişmesiyle sonuçlanabileceği için farklı paylaşılan kaynaklar için aynı kilit nesnesi örneğini kullanmaktan kaçının. Özellikle, aşağıdaki türleri kilit nesneleri olarak kullanmaktan kaçının:

  • this, arayanlar tarafından kilit olarak kullanılabildiğinden.
  • Type örnekleri, bu nesneler typeof işleci veya yansıma tarafından elde edilebilir.
  • dize değişmez değerleri de dahil olmak üzere dize örnekleri, dize değişmez değerlerine dahil edilebilir.

Kilit çekişmesini azaltmak için mümkün olduğunca kısa bir süre için bir kilit tutun.

Örnek

Aşağıdaki örnek, özel alanına erişimi balance ayrılmış balanceLock bir örneğe kilitleyerek eşitleyen bir sınıf tanımlarAccount. Kilitleme için aynı örneği kullanmak, alanın veya Credit yöntemlerini aynı anda çağırmaya Debit çalışan iki iş parçacığı tarafından aynı anda güncelleştirilmesini sağlarbalance.

using System;
using System.Threading.Tasks;

public class Account
{
    private readonly object balanceLock = new object();
    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));
            }
        }
    }
}

C# dili belirtimi

Daha fazla bilgi için C# dil belirtimininkilit deyimi bölümüne bakın.

Ayrıca bkz.