伴隨著賦值操作的引入脖苏,時(shí)間屬性也被同時(shí)引入了計(jì)算對(duì)象中样屠。對(duì)于非時(shí)間性的函數(shù)式編程可以通過同時(shí)運(yùn)行幾組任務(wù)提高整個(gè)系統(tǒng)的計(jì)算效率,但是對(duì)于含有賦值操作的計(jì)算對(duì)象將涉及共享狀態(tài)問題,在不加以限制的情況下進(jìn)行并發(fā)操作只會(huì)導(dǎo)致錯(cuò)誤的結(jié)果莉御。
保持并發(fā)系統(tǒng)行為的正確性需要嚴(yán)格的條件疙渣,這些條件極度脆弱匙奴,所以不得不施加額外的限制以保障并發(fā)系統(tǒng)計(jì)算結(jié)果的正確性。關(guān)于并發(fā)系統(tǒng)的控制方法有很多妄荔,這里只介紹其中的一種 串行器(serializer)泼菌。
串行器能夠?qū)⒊淌酱谢苊猱?dāng)前程式在執(zhí)行過程中被其他進(jìn)程的程式操作共享狀態(tài)導(dǎo)致計(jì)算結(jié)果錯(cuò)誤啦租。具體使用方式如下哗伯。
(define s (make-serializer))
(parallel-execute
(s (lambda () (set! x (* x x))))
(s (lambda () (set! x (+ x 1)))))
其中串行器的實(shí)現(xiàn)需要通過 互斥元(mutex) 機(jī)制實(shí)現(xiàn),互斥元可以被持有和釋放篷角,但當(dāng)它被持有時(shí)其他進(jìn)程無法持有它焊刹,只能通過循環(huán)等待的方式等到互斥元被釋放時(shí)才能持有。下面是通過互斥元實(shí)現(xiàn)的串行器恳蹲。
(define (make-serializer)
(let ((mutex (make-mutex)))
(lambda (p)
(define (serialized-p . args)
(mutex 'acquire)
(let ((val (apply p args)))
(mutex 'release)
val))
serialized-p)))
互斥元的實(shí)現(xiàn)通過 單元(cell) 中的值實(shí)現(xiàn)虐块,單元是一個(gè)只有一個(gè)元素的列表,這個(gè)元素的值只能是 true 或 false阱缓,其中 true 表示互斥元處于持有狀態(tài)非凌,false 則相反。下列是關(guān)于互斥元的具體實(shí)現(xiàn)荆针。
(define (make-mutex)
(let ((cell (list false)))
(define (the-mutex m)
(cond ((eq? m 'acquire)
(if (test-and-set! cell)
(the-mutex 'acquire))) ;retry
((eq? m 'release) (clear! cell))))
the-mutex))
(define (clear! cell) (set-car! cell false))
(define (test-and-set! cell)
(if (car cell) true (begin (set-car! cell true) false)))
不過 test-and-set!
程式的實(shí)現(xiàn)并不滿足標(biāo)準(zhǔn)敞嗡,因?yàn)?test-and-set!
是并發(fā)系統(tǒng)的核心颁糟,整個(gè)操作要保持原子性,否則會(huì)由于并發(fā)操作導(dǎo)致計(jì)算結(jié)果錯(cuò)誤喉悴,而 test-and-set!
的具體實(shí)現(xiàn)與系統(tǒng)對(duì)并發(fā)進(jìn)程的運(yùn)行處理有關(guān)棱貌。
除此之外,在面對(duì)多資源共享的情況下箕肃,還會(huì)出現(xiàn)由于不同進(jìn)程互相持有對(duì)方正在等待的互斥元導(dǎo)致死鎖問題婚脱。有些死鎖問題可以通過添加控制機(jī)制避免,但有的死鎖問題根本無法避免勺像。