세마포에 대한 지식이있는 한 세마포는 계산할 수 있고 경쟁 조건에 취약한 리소스를 보호하는 데 사용됩니다. 그러나 세마포어에 대한 SBCL 문서를 읽는 동안 제공된 세마포어 구현을 사용하여 리소스를 보호하는 방법을 알 수 없었습니다.SBCL이 경쟁 조건에 대해 제공 한 세마포어를 사용하는 방법
자주 수행 작업 흐름, 나는 것 기억으로 :
는프로세스는 세마포어로의 일부를 검색하고 싶어 (예 사소한 큐의 이익을 위해입니다) 데이터를 보호. 세마포어 카운터가 0으로, 과정은
다른 프로세스가 큐에 무언가를두고 세마포어가 증가 같이, 신호가 가능성을 감안할 때 모든 대기 프로세스
로 전송 대기 인터리빙을 위해서는 자원 순서가 아닐 수도 있고 선형 순서가 아닐 수도 있으므로 자원 액세스를 보호해야합니다. 따라서. Java는 각 클래스를 암시 적 모니터로 해석하고 syncronized
키워드를 제공하여 프로그래머가 한 번에 하나의 프로세스에서만 액세스 할 수있는 보호 영역을 정의 할 수 있습니다.
세마포어가 보호 할 코드가 없으므로 현재 코드가 세마포어없이 스레드 안전하다고 확신하므로 common-lisp에서이 기능을 에뮬레이션하는 방법.
;;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)
잘 세마포어에 자물쇠를 사용하는 것이 두 가지 가능성을 열어줍니다 : (a) 프로세스가 세마포어를 기다리지 만 외부를 반환하지 않으면 교착 상태가 발생할 수 있으므로 매우 위험합니다. lock (b) 자물쇠 밖에서 세마포를 사용하십시오. 그렇다면 아무 것도 얻을 수없는 멋진 카운터를 얻었습니다. 나는 주어진 구현이 코드를 보호하는 깔끔한 방법을 제공하기를 희망했다. 그러한 가능성이없는 경우. 내 발언 (a)에서 편집하십시오. 나는 대답으로 받아 들일 것입니다. (당신이 다른 물건에 대해서도 맞습니다.) – Sim
@Sim, 오케이, 나는 내 대답에 당신의 말을 추가 할 것입니다. 또한, 세마포어를 사용하여 무언가를 얻으십시오 : 수동 대기 및 여러 웨이터를 연속적으로 깨우기. – acelent
@Sim, 처음 단락에 몇 단어를 추가하여 더 명확하게했습니다. 이전 버전에서는 독점 리소스 액세스에 대한 잠금을 사용하는 것이 세마포어 대신 사용되었다는 인상을 줄 수있었습니다. – acelent