Spinlock khác với bỏ phiếu như thế nào?


41

Là spinlock và bỏ phiếu giống nhau?

Wikipedia:

spinlock là một khóa khiến cho một luồng cố gắng thu được nó chỉ đơn giản là chờ trong một vòng lặp ("spin") trong khi liên tục kiểm tra xem khóa có sẵn không

Điều này nghe có vẻ rất giống như:

while(!ready);

Tôi đã được dạy để tránh bỏ phiếu bất cứ khi nào có thể vì nó là tối ưu phụ. Vì vậy, spinlock là một cái tên ưa thích cho bỏ phiếu cũ xấu? Làm thế nào là một spinlock khác với bỏ phiếu?

Câu trả lời:


85

Bỏ phiếu đề cập đến việc kiểm tra nhiều lần xem một tài nguyên ( bất kỳ loại tài nguyên nào) đã sẵn sàng chưa.

Một spinlock là khi tài nguyên bạn đang bỏ phiếu là một khóa.

Lưu ý rằng bỏ phiếu không phải là xấu. Cụ thể, bỏ phiếu hiệu quả khi thường có dữ liệu sẵn sàng khi bạn bỏ phiếu. Bỏ phiếu chỉ không hiệu quả nếu bạn làm điều đó mà không nhận được bất kỳ dữ liệu nào.

Mặt khác, các ngắt là không hiệu quả nếu có quá nhiều dữ liệu khiến bạn liên tục bị gián đoạn. Chúng rất hiệu quả nếu dữ liệu đến hiếm khi đủ để bạn thực sự có thể hoàn thành một số công việc hữu ích trước khi bị gián đoạn.

Tôi có thể cho bạn một ví dụ thực tế từ kinh nghiệm của chính tôi: 15 năm trước, tôi đã thiết lập chương trình email của mình để làm gián đoạn tôi mỗi khi có email mới đến. Điều đó xảy ra một hoặc hai lần một tuần. Liên tục kiểm tra hộp thư đến của tôi sẽ là một sự lãng phí thời gian khổng lồ.

Ngày nay, tôi đã tắt tất cả các thông báo. Tôi biết rằng bất cứ khi nào tôi nhìn vào hộp thư đến của mình, sẽ có email mới ở đó. Bỏ phiếu hiệu quả hơn nhiều bây giờ.

Spinlocks có hiệu quả khi a) khả năng khóa được lấy thấp và b) nếu khóa được thực hiện, nó sẽ chỉ được giữ trong một thời gian ngắn. Nói cách khác: nó hiệu quả đối với các khóa hạt mịn hầu như không được bảo vệ, nhưng không hiệu quả đối với các khóa hạt thô có nhiều cạnh tranh.

(Và tất nhiên, spinlocks chỉ hoạt động khi có sự song song thực sự, nếu không thì các luồng khác sẽ không có cơ hội để mở khóa. Tôi đoán đó là điều hiển nhiên, nhưng dù sao tôi cũng muốn nói rõ.)


5
Spinlocks có thể hoàn toàn hợp lý trong một môi trường hợp tác đa nhiệm. Bạn chỉ cần đảm bảo rằng bạn đạt được kiểm soát trong vòng lặp.
Kevin

4
Ví dụ tuyệt vời với email. Nhắc tôi nhớ về bạn luôn có email ...
Petr Pudlák

2
@Kevin: Tôi có một ý tưởng rất thuần túy về một spinlock, nghĩa đen là một khóa chỉ quay trong một vòng lặp trống. ( atomically_do { while (lock.is_locked?); lock.acquire! }) Nếu nó mang lại, nó không phải là một vòng lặp trống rỗng và do đó không phải là một spinlock trong quan điểm thuần túy đó :-D Nhưng tất nhiên một số phép lai với các loại khóa hoặc thư giãn / bổ sung cho lý tưởng thuần túy có ý nghĩa hoàn hảo trong thế giới thực.
Jörg W Mittag

3
@bubakazouba: Một spinlock hoạt động theo nghĩa đen là "quay" trong một vòng lặp trống và kiểm tra "Khóa đã được giải phóng chưa? Khóa đã được giải phóng chưa? Khóa đã được giải phóng chưa? Khóa đã được giải phóng chưa? Khóa đã được giải phóng chưa?" lặp đi lặp lại. Nếu không có sự song song, thì không có luồng nào khác chạy cùng lúc có thể giải phóng khóa, vì vậy bạn thực sự có một vòng lặp vô tận! Xem bình luận trực tiếp trên của bạn.
Jörg W Mittag

1
@kasperd: Bạn vẫn có thể thấy đa nhiệm hợp tác trong phần mềm máy chủ điều khiển sự kiện như nginx. Trong trường hợp đó, có một luồng và không khóa, có nghĩa là bạn chỉ có thể khai thác một lõi. Theo hiểu biết tốt nhất của tôi, thực sự không có ví dụ thực tế nào về đa nhiệm hợp tác đa lõi thực sự. Một hệ thống như vậy sẽ là ngu ngốc, vì bạn sẽ nhận được tất cả các nhược điểm của đa nhiệm hợp tác mà không có mặt trái của khóa.
Kevin

10

Spinlock là một loại khóa, cụ thể, một khóa đạt được thông qua bỏ phiếu.

Bỏ phiếu là một phương pháp kiểm tra trạng thái của một cái gì đó (bằng cách yêu cầu trạng thái, trái ngược với việc chờ đợi để được nói trạng thái).

Không phải tất cả các cuộc bỏ phiếu là một spinlock, ví dụ, bỏ phiếu trạng thái của các phím bàn phím.


Ngoài ra, bỏ phiếu không phải là xấu. Thời gian bỏ phiếu rất ngắn có thể tránh được những thay đổi bối cảnh đắt tiền mà việc sử dụng ngắt sẽ yêu cầu, chưa kể rằng việc bỏ phiếu đôi khi có thể đơn giản hơn để thực hiện và do đó dễ duy trì hơn, đặc biệt là ở cấp thấp hơn. Như thường lệ, tuyệt đối là một điều tồi tệ, và bạn nên sử dụng phương pháp mang lại hiệu suất / độ phức tạp phù hợp cho nhu cầu của bạn như bạn đã đo lường chúng , thay vì sử dụng hoặc loại bỏ các tùy chọn một cách mù quáng.


5

Spinlock khác với bỏ phiếu vì nó chỉ xảy ra trong một khoảng thời gian rất ngắn, theo thứ tự vài mili giây hoặc ít hơn. Bỏ phiếu có thể tiếp tục vô thời hạn.

Trong lập trình song song, một đoạn ngắn của kéo sợi thường thích hợp hơn để chặn, vì nó tránh được chi phí chuyển đổi ngữ cảnh và chuyển đổi kernel.

Đọc thêm
SpinLock và SpinWait trong C #
Spinlocks và Khóa đọc-ghi trong C


Tôi nghĩ rằng bạn có nghĩa là để nói micro giây. Đối với một khóa kéo dài toàn bộ mili giây, chúng ta nên sử dụng cài đặt khóa thực hiện cuộc gọi kernel khi tranh chấp.
Peter

@Peter Có lẽ đó là những gì Albahari muốn nói. Đó là những gì văn bản của ông nói.
Robert Harvey

4

Sự khác biệt là một spinlock (hy vọng) chỉ được sử dụng trong các tình huống phù hợp, và trong những tình huống này, nó rất hiệu quả.

Bạn sử dụng spinlock nếu bạn cho rằng tài nguyên sẽ chỉ bị khóa trong một thời gian rất ngắn - ví dụ: nếu khóa chỉ được sử dụng để cập nhật một biến. Spinlock thăm dò khóa ở tốc độ tối đa, nhưng hy vọng trong ít hơn micro giây. Một mutex bình thường sẽ yêu cầu cuộc gọi hệ điều hành. NẾU khóa chỉ được giữ trong một khoảng thời gian nhỏ, thì spinlock chỉ sử dụng một lượng nhỏ thời gian CPU, trong khi cuộc gọi hệ điều hành sẽ mất nhiều thời gian hơn. Nhưng nếu kỳ vọng này là sai, thì spinlock rất kém hiệu quả - nó sẽ sử dụng 100% thời gian CPU trên một CPU, trong khi mutex bình thường chỉ mất thời gian để vào HĐH và quay trở lại.

Đôi khi cả hai được kết hợp; bạn chạy khóa spin trong một thời gian ngắn và chuyển sang một chiến lược khác nếu spinlock không hoạt động.


2

Bỏ phiếu quá mức là điều bạn không nên làm vì nó lãng phí tài nguyên hệ thống. Theo đó, việc bỏ phiếu là ổn nếu nó không lãng phí tài nguyên hệ thống .

Ví dụ, bỏ phiếu quá mức sẽ tải CPU đến 100% trong trường hợp công việc thực tế chỉ dẫn đến tải 2%.

Bỏ phiếu có thể được sử dụng cho những thứ khác hơn while(!ready). Ví dụ, nó có nghĩa là kiểm tra thường xuyên nếu người dùng nhấn một phím. Việc triển khai lành mạnh sẽ kiểm tra tối đa cứ sau 15 mili giây, do đó, một lần kiểm tra cứ sau 20 triệu chu kỳ đồng hồ. Loại bỏ phiếu đó là tuyệt vời, vì nó không lãng phí tài nguyên hệ thống.

SpinLock không phải là trường hợp đặc biệt. Nếu chúng ta có SpinLock và một luồng vào khóa và một luồng khác phải chờ, thì SpinLock là lựa chọn sai khi và chỉ khi luồng chờ làm lãng phí tài nguyên hệ thống. Chuỗi chờ sẽ lãng phí tài nguyên hệ thống nếu và chỉ khi nó phải chờ trong một khoảng thời gian đáng kể trước khi có thể có được khóa.

Do đó, sử dụng SpinLock để bảo vệ bất cứ thứ gì cần vài nghìn chu kỳ đồng hồ trở lên trước khi mở lại (ví dụ: biên dịch và thực thi một đoạn javascript khi đang hoạt động) là chính xác, vì lý do bạn đã nêu. Nhưng sử dụng SpinLock để bảo vệ thứ gì đó hoàn thành nhanh chóng, như truy cập bản đồ băm được triển khai đúng cách là tốt vì luồng chờ sẽ chỉ quay 2 hoặc 3 lần và do đó không làm lãng phí tài nguyên hệ thống.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.