2012-04-11 45 views
7

Tôi đã viết mã đơn giản (kèm theo) và tôi không hiểu tại sao khóa trên một số khối không khóa phạm vi.Tại sao khóa trong mã này không hoạt động?

Mã:

object locker = new object(); 
    private void foo(int i) 
    { 
     Console.WriteLine(string.Format("i is {0}", i)); 
     lock(locker) 
     { 
      while(true) 
      { 
       Console.WriteLine(string.Format("i in while loop is {0}", i)) ; 
       foo(++i); 
      } 
     } 
    } 

tôi hy vọng rằng sự kêu gọi đối với phương pháp foo trong vòng lặp while sẽ chờ đợi cho đến khi thay đồ sẽ được phát hành (thay đồ phạm vi) - nhưng tất cả các cuộc gọi của foo với arg của ++ tôi có thể nhập vào khối thay đồ.

+0

Tôi nghĩ rằng cùng một chủ đề của nó nên không khóa chính nó (có thể ai đó biết chi tiết hơn) – V4Vendetta

+0

tôi chắc chắn đã học được điều gì đó mới mẻ này, +1 –

+11

Nếu bạn đã ở trong phòng tắm, và cửa là đã bị khóa, và bạn đặt một khóa * thứ hai trên cửa, * bạn vẫn còn trong phòng tắm rồi. * –

Trả lời

12

Khóa được sử dụng ở đây là reentrant. Nó sẽ ngăn chặn một thread khác đi vào màn hình, nhưng thread giữ khóa sẽ không bị chặn.

+0

Tôi không biết đó là cách nó hoạt động - bạn 100% ở bên phải này? –

+2

@Gabriel Điều này là chính xác; câu lệnh 'lock' trong C# là tái nhập. Bạn không thể khóa "chính mình" ra. – dlev

+0

đó không phải là những gì xảy ra trong C/C++, trừ khi bộ nhớ của tôi bị bắn (và có thể là vậy) - thật ngạc nhiên khi tôi chưa bao giờ nhận ra sự khác biệt như vậy –

7

Từ khóa khóa chỉ là cú pháp đường xung quanh các phương pháp Monitor.EnterMonitor.Exit. Như đã thấy trong số documentation cho Monitor:

Đó là hợp pháp cho cùng một chuỗi để gọi Nhập nhiều lần mà không chặn;

Gọi lock(object) từ cùng một chuỗi nhiều lần không có tác dụng khác ngoài việc tăng số lượng khóa.

+0

là có một loại khóa hoạt động theo cách áp phích mong đợi Màn hình/khóa để hành xử? –

+1

@Gabriel, bạn có thể sử dụng 'AutoResetEvent' cho điều đó. – svick

+1

@Gabriel 'SpinLock' không được tái nhập, IOW,' SpinLonk.Enter' sẽ thất bại nếu được gọi trên cùng một luồng đã giữ khóa; cả hai không chính xác như nhau nhưng sẽ làm việc như OP dường như mong đợi. –

1

Khi bạn thực hiện một cuộc gọi đệ quy ở đây trên chuỗi nói t1, nó không quay ra một sợi riêng biệt. Cuộc gọi đệ quy đang được thực hiện trên cùng một chuỗi t1.

Vì t1 đã giữ khóa, nó không phải chờ khóa.

Các vấn đề liên quan