2009-03-25 38 views
6

Nếu bạn có hai luồng gọi hàm tĩnh tại cùng một thời điểm, có nguy cơ đồng thời không? Và nếu hàm đó sử dụng một thành viên tĩnh của lớp, thì có vấn đề lớn hơn không?Đồng thời chức năng tĩnh ASP.NET

  • Hai cuộc gọi có tách biệt với nhau không? (chức năng giống như được sao chép cho hai luồng?)
  • Chúng có được tự động xếp hàng không?

Ví dụ trong ví dụ tiếp theo, có rủi ro không?

private static int a = 5; 

public static int Sum() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

Ví dụ tiếp theo, có rủi ro không?

public static int Sum2() 
{ 
    int a = 5; 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

Cập nhật: Và quả thực, nếu cả hai chức năng trong cùng một lớp, rủi ro là gì sau đó?

thx, Lieven Cardoen

Trả lời

10

Có, có rủi ro đồng thời khi bạn sửa đổi biến tĩnh trong phương pháp tĩnh.

Bản thân các hàm tĩnh có bộ biến cục bộ riêng biệt, nhưng bất kỳ biến tĩnh nào đều được chia sẻ.

Trong các mẫu cụ thể của bạn, bạn không bị phơi nhiễm, nhưng đó chỉ là vì bạn đang sử dụng các hằng số (và gán cùng giá trị cho chúng). Thay đổi mẫu mã một chút và bạn sẽ được tiếp xúc.

Edit:

Nếu bạn gọi cả sum1() VÀ Sum2() từ chủ đề khác nhau mà bạn đang gặp rắc rối, không có cách nào để đảm bảo giá trị của a và b trong bản Tuyên Bố này: int c = a + b;

private static int a = 5; 

public static int Sum1() 
{ 
    int b = 4; 
    a = 9; 
    int c = a + b; 
    return c; 
} 

public static int Sum2() 
{ 
    int b = 4; 
    int c = a + b; 
    return c; 
} 

Bạn cũng có thể đạt được các vấn đề đồng thời với nhiều lời gọi của một phương pháp đơn như thế này:

public static int Sum3(int currentA) 
{ 
    a = currentA; 
    int b = 4; 
    int c = a + b; 
    int d = a * b; // a may have changed here 
    return c + d; 
} 

Vấn đề ở đây là giá trị của một có thể thay đổi giữa phương pháp do khác các lời gọi thay đổi nó.

+0

tôi đã thay đổi ví dụ đầu tiên. Bây giờ nó có lẽ không phải là chủ đề an toàn nữa? –

+0

Có tài liệu tham khảo, sách, liên kết tốt về chủ đề này không + cách bạn có thể giải quyết những tình huống này? –

+0

http://www.amazon.com/Concurrent-Programming-Java-TM-Principles/dp/0201310090/ref=pd_bbs_sr_3?ie=UTF8&s=books&qid=1237967873&sr=8-3 sẽ phục vụ bạn tốt – krosenvold

1

Trong hai ví dụ của bạn, không có vấn đề an toàn luồng vì mỗi cuộc gọi đến hàm sẽ có bản sao riêng của biến cục bộ trên ngăn xếp và trong ví dụ đầu tiên của bạn có 'a' là biến tĩnh, bạn không bao giờ thay đổi 'a', vì vậy không có vấn đề gì.

Nếu bạn thay đổi giá trị trong 'a' trong ví dụ đầu tiên của mình, bạn sẽ gặp phải vấn đề tương tranh tiềm ẩn.

+0

Đúng, không nhận thấy rằng Biến A không được sửa đổi, vì vậy tất cả đều tốt với mã mà chúng ta CÓ THỂ thấy. Có khả năng nó có thể được sửa đổi bên ngoài mã hiển thị –

+0

Thay đổi nó. Lấy làm tiếc. Ví dụ đầu tiên là không tốt. –

1

Nếu phạm vi của các biến được chứa bên trong hàm tĩnh thì không có rủi ro, nhưng các biến ngoài phạm vi chức năng (tĩnh/chia sẻ) chắc chắn là đặt ra một nguy cơ đồng thời

3

Vâng, có một nguy cơ. Đó là lý do tại sao bạn sẽ thấy trong tài liệu MSDN, nó thường sẽ nói "Lớp này là luồng an toàn cho các thành viên tĩnh" (hoặc một cái gì đó như thế).Nó có nghĩa là khi MS đã viết mã, họ cố tình sử dụng đồng bộ nguyên thủy để làm cho các thành viên tĩnh threadsafe. Điều này là phổ biến khi viết các thư viện và khung công tác, vì nó dễ dàng hơn để làm cho các thành viên tĩnh trở thành luồng an toàn hơn các thành viên cá thể, bởi vì bạn không biết người dùng thư viện sẽ muốn làm gì với các cá thể. Nếu họ tạo ra các cá thể thành viên cho các lớp thư viện, chúng sẽ đặt quá nhiều hạn chế cho bạn ... vì vậy chúng thường cho phép bạn xử lý nó.

Vì vậy, bạn cũng cần phải làm cho các thành viên tĩnh của bạn an toàn (hoặc tài liệu mà họ không có).

Nhân tiện, các nhà thầu tĩnh là chủ đề an toàn theo nghĩa. CLR sẽ đảm bảo rằng chúng được gọi chỉ một lần và sẽ ngăn 2 chủ đề đi vào một hàm tạo tĩnh.

CHỈNH SỬA: Marc chỉ ra trong các chú thích một trường hợp cạnh trong đó các hàm tạo tĩnh không phải là luồng an toàn. Nếu bạn sử dụng sự phản chiếu để gọi một constructor tĩnh một cách rõ ràng, rõ ràng bạn có thể gọi nó nhiều hơn một lần. Vì vậy, tôi sửa lại câu lệnh như sau: miễn là bạn đang dựa vào CLR để quyết định khi nào gọi hàm dựng tĩnh của bạn, thì CLR sẽ ngăn không cho nó được gọi nhiều lần, và nó cũng sẽ ngăn chặn ctor tĩnh được gọi tái entrantly.

+0

Thực ra, không, nó không * đảm bảo * điều này - bạn có thể gọi kiểu khởi tạo kiểu thông qua sự phản chiếu tầm thường, trong trường hợp này bạn có thể gọi nó nhiều lần cùng một lúc. –

+0

Ah, thú vị. Tôi không bao giờ nghĩ về điều đó. Điểm tốt.Tuy nhiên, miễn là bạn tránh gọi nó một cách rõ ràng thông qua sự phản ánh, bạn có thể dựa vào CLR để làm cho nó an toàn hơn. Điều đó có ích đôi khi. –

3

Xem here để thảo luận về biến cục bộ. trước khi chỉnh sửa không phải phương pháp nào ở trên mình có rủi ro đồng thời; các biến cục bộ đều độc lập cho mỗi cuộc gọi; trạng thái được chia sẻ (static int a) hiển thị với nhiều chuỗi, nhưng bạn không biến đổi nó, và bạn chỉ đọc nó một lần.

Nếu bạn đã làm điều gì đó như:

if(a > 5) { 
    Console.WriteLine(a + " is greater than 5"); 
} // could write "1 is greater than 5" 

nó sẽ (về mặt lý thuyết) không được an toàn, như giá trị của một có thể thay đổi bởi thread khác - bạn sẽ thường hoặc đồng bộ hóa truy cập (thông qua lock vv) hoặc chụp nhanh:

int tmp = a; 
if(tmp > 5) { 
    Console.WriteLine(tmp + " is greater than 5"); 
} 

Nếu bạn đang chỉnh sửa giá trị, bạn gần như chắc chắn sẽ yêu cầu đồng bộ hóa.

+0

Thx. Xin lỗi vì chỉnh sửa. –

1

Phương pháp tĩnh trong OO không khác biệt với chức năng "chỉ" trong lập trình thủ tục. Trừ khi bạn lưu trữ một số trạng thái bên trong biến tĩnh không có rủi ro nào cả.

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