it-swarm-vi.tech

Làm thế nào để khóa hoạt động chính xác?

Tôi thấy rằng để sử dụng các đối tượng không phải là luồng an toàn, chúng tôi bọc mã bằng một khóa như thế này:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

Vì vậy, điều gì xảy ra khi nhiều luồng truy cập cùng một mã (giả sử rằng nó đang chạy trong một ứng dụng web ASP.NET). Họ có xếp hàng không? Nếu vậy họ sẽ đợi bao lâu?

Tác động hiệu suất vì sử dụng ổ khóa là gì?

452
NLV

Câu lệnh lock được dịch bởi C # 3.0 như sau:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

Trong C # 4.0 điều này đã thay đổi và bây giờ nó được tạo như sau:

bool lockWasTaken = false;
var temp = obj;
try
{
    Monitor.Enter(temp, ref lockWasTaken);
    // body
}
finally
{
    if (lockWasTaken)
    {
        Monitor.Exit(temp); 
    }
}

Bạn có thể tìm thêm thông tin về những gì Monitor.Enter làm tại đây . Để trích dẫn MSDN:

Sử dụng Enter để thu được Màn hình trên đối tượng được truyền dưới dạng tham số. Nếu một luồng khác đã thực thi Enter trên đối tượng nhưng chưa thực thi Exit tương ứng, thì luồng hiện tại sẽ chặn cho đến khi luồng khác giải phóng đối tượng. Nó là hợp pháp cho cùng một chủ đề để gọi Enter nhiều lần mà không bị chặn; tuy nhiên, một số lượng cuộc gọi Exit bằng nhau phải được gọi trước khi các luồng khác đang chờ trên đối tượng sẽ bỏ chặn.

Phương thức Monitor.Enter sẽ chờ vô hạn; nó sẽ không hết thời gian .

402
Steven

Nó đơn giản hơn bạn nghĩ.

Theo Microsoft : Từ khóa lockđảm bảo rằng một luồng không nhập một phần quan trọng của mã trong khi một luồng khác nằm trong phần quan trọng. Nếu một luồng khác cố gắng nhập mã bị khóa, nó sẽ chờ, chặn, cho đến khi đối tượng được giải phóng.

Từ khóa lockgọi EnterNAME _ ở đầu khối và ExitNAME _ ở cuối khối. locktừ khóa thực sự xử lý MonitorNAME _ lớp ở cuối.

Ví dụ:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

Trong đoạn mã trên, đầu tiên, luồng vào phần quan trọng và sau đó nó sẽ khóa objname__. Khi một luồng khác cố gắng nhập, nó cũng sẽ cố gắng khóa objname__, đã bị khóa bởi luồng đầu tiên. Tôi sẽ phải đợi chủ đề đầu tiên phát hành objname__. Khi luồng đầu tiên rời đi, thì một luồng khác sẽ khóa objvà sẽ vào phần quan trọng.

238
Umar Abbas

Không, họ không được xếp hàng, họ đang ngủ

Một tuyên bố khóa của mẫu

lock (x) ... 

trong đó x là biểu thức của kiểu tham chiếu, chính xác tương đương với

var temp = x;
System.Threading.Monitor.Enter(temp); 
try { ... } 
finally { System.Threading.Monitor.Exit(temp); }

Bạn chỉ cần biết rằng họ đang đợi nhau và chỉ một luồng sẽ nhập vào khối khóa, những người khác sẽ đợi ...

Màn hình được viết hoàn toàn bằng .net vì vậy nó đủ nhanh, hãy nhìn vào lớp Monitor với gương phản xạ để biết thêm chi tiết

43
Arsen Mkrtchyan

Khóa sẽ chặn các luồng khác thực thi mã có trong khối khóa. Các luồng sẽ phải đợi cho đến khi luồng trong khối khóa hoàn thành và khóa được giải phóng. Điều này có tác động tiêu cực đến hiệu suất trong môi trường đa luồng. Nếu bạn cần phải làm điều này, bạn nên đảm bảo mã trong khối khóa có thể xử lý rất nhanh. Bạn nên cố gắng tránh các hoạt động đắt tiền như truy cập cơ sở dữ liệu, v.v.

26
Andrew

Tác động hiệu suất phụ thuộc vào cách bạn khóa. Bạn có thể tìm thấy một danh sách tối ưu hóa tốt ở đây: http://www.thinkingabul.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/ = =

Về cơ bản, bạn nên cố gắng khóa càng ít càng tốt, vì nó đặt mã chờ của bạn vào trạng thái ngủ. Nếu bạn có một số tính toán nặng hoặc mã kéo dài (ví dụ: tải lên tệp) trong một khóa, điều đó dẫn đến mất hiệu suất rất lớn.

10
Simon Woker

Phần trong câu lệnh khóa chỉ có thể được thực thi bởi một luồng, vì vậy tất cả các luồng khác sẽ chờ vô thời hạn cho nó, luồng giữ khóa kết thúc. Điều này có thể dẫn đến cái gọi là bế tắc.

7
Mr47

Câu lệnh lockđược dịch thành các cuộc gọi đến các phương thức EnterExitcủa MonitorNAME _ .

Câu lệnh locksẽ chờ vô thời hạn để đối tượng khóa được phát hành.

7
Paolo Tedesco

khóa thực sự bị ẩn Màn hình lớp.

4
Euphoric