Theo như kiến thức của tôi về semaphores đi, một semaphore được sử dụng để bảo vệ tài nguyên có thể được tính và dễ bị điều kiện chủng tộc. Nhưng trong khi đọc tài liệu của SBCL về các semaphores tôi không thể tìm ra, làm thế nào để sử dụng đúng cách thực hiện semaphore được cung cấp để bảo vệ tài nguyên.Làm thế nào để sử dụng SBCL cung cấp semaphore chống lại điều kiện chủng tộc
Một luồng công việc thường lệ, khi tôi gọi lại sẽ là:
một quá trình muốn lấy một số các bằng semaphore bảo vệ dữ liệu (đó là vì lợi ích của ví dụ một hàng đợi tầm thường). Khi semaphore đếm là 0, quá trình chờ đợi
quá trình khác đặt một cái gì đó trong hàng đợi và như semaphore là tăng lên, một tín hiệu được gửi đến tất cả các quá trình chờ đợi
Với khả năng xen kẽ, người ta phải bảo vệ bất kỳ truy cập tài nguyên nào như chúng có thể không theo thứ tự đó, hoặc bất kỳ thứ tự tuyến tính nào cả. Vì vậy, ví dụ: Java diễn giải từng lớp dưới dạng một giám sát ngầm và cung cấp một từ khóa syncronized
mà một lập trình viên có thể định nghĩa một khu vực được bảo vệ mà chỉ có thể được truy cập bởi một tiến trình tại một thời điểm.
Làm cách nào để mô phỏng chức năng này theo ngôn ngữ chung, vì tôi khá chắc chắn mã hiện tại của tôi là an toàn chủ đề không có semaphore, vì semaphore không có đầu mối để bảo vệ.
;;the package
(defpackage :tests (:use :cl :sb-thread))
(in-package :tests)
(defclass thread-queue()
((semaphore
:initform (make-semaphore :name "thread-queue-semaphore"))
(in-stack
:initform nil)
(out-stack
:initform nil)))
(defgeneric enqueue-* (queue element)
(:documentation "adds an element to the queue"))
(defgeneric dequeue-* (queue &key timeout)
(:documentation "removes and returns the first element to get out"))
(defmethod enqueue-* ((queue thread-queue) element)
(signal-semaphore (slot-value queue 'semaphore))
(setf (slot-value queue 'in-stack) (push element (slot-value queue 'in-stack))))
(defmethod dequeue-* ((queue thread-queue) &key timeout)
(wait-on-semaphore (slot-value queue 'semaphore) :timeout timeout)
(when (= (length (slot-value queue 'out-stack)) 0)
(setf (slot-value queue 'out-stack) (reverse (slot-value queue 'in-stack)))
(setf (slot-value queue 'in-stack) nil))
(let ((first (car (slot-value queue 'out-stack))))
(setf (slot-value queue 'out-stack) (cdr (slot-value queue 'out-stack)))
first))
(defparameter *test* (make-instance 'thread-queue))
(dequeue-* *test* :timeout 5)
(enqueue-* *test* 42)
(enqueue-* *test* 41)
(enqueue-* *test* 40)
(dequeue-* *test* :timeout 5)
(dequeue-* *test* :timeout 5)
(dequeue-* *test* :timeout 5)
(dequeue-* *test* :timeout 5)
cũng sử dụng khóa bổ sung cho semaphore sẽ mở ra hai khả năng: (a) sử dụng semaphore bên trong khóa -> rất nguy hiểm vì điều này có thể dẫn đến bế tắc nếu quá trình chờ semaphore nhưng không trả về bên ngoài khóa (b) sử dụng semaphore bên ngoài khóa -> tốt, sau đó tôi đã đạt được gì, nhưng một truy cập ưa thích tôi có thể đã thực hiện bản thân mình. Tôi hy vọng triển khai được cung cấp sẽ cung cấp một cách gọn gàng để bảo mật mã. Nếu không có khả năng như vậy. Xin vui lòng chỉnh sửa trong nhận xét của tôi (a) và tôi sẽ chấp nhận nó như là một câu trả lời. (Bạn có quyền về những thứ khác) – Sim
@Sim, ok, tôi sẽ thêm nhận xét của bạn vào câu trả lời của tôi. Ngoài ra, lưu ý rằng bạn có được một cái gì đó với semaphores: thụ động chờ đợi và đánh thức nhiều bồi bàn liên tiếp. – acelent
@Sim, tôi đã thêm một vài từ vào các đoạn ban đầu để làm cho chúng rõ ràng hơn. Phiên bản trước đó có thể tạo ấn tượng rằng việc sử dụng khóa để truy cập tài nguyên độc quyền là một thay thế cho các ẩn dụ. – acelent