英文:
About serializers as a mechanism for dealing with concurrency
问题
是的,你的结论是正确的。
英文:
tl;dr
Is changing the former snippet below for the latter safe?
Complete question
In section §3.4.2 from SICP, the following function for creating an account balance able to cope with concurrent requests is shown at page 305:
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(let ((protected (make-serializer)))
(define (dispatch m)
(cond ((eq? m 'withdraw) (protected withdraw))
((eq? m 'deposit) (protected deposit))
((eq? m 'balance) balance)
(else (error " Unknown request -- MAKE-ACCOUNT"
m))))
dispatch))
where a serializer named protected
is created via (protected (make-serializer))
in the let
statement, and subsequently used to create, out of withdraw
and deposit
two functions that do the same thing as those two, but whose executions cannot interleave.
Later, in exercise 3.42 at page 307, the following alternative version is shown, and the question is whether the change is safe.
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(let ((protected (make-serializer)))
(let ((protected-widthdraw (protected widthdraw)) ; these lines
(protected-deposit (protected deposit))) ; are added
(define (dispatch m)
(cond ((eq? m 'withdraw) protected-withdraw)
((eq? m 'deposit) protected-deposit)
((eq? m 'balance) balance)
(else (error " Unknown request -- MAKE-ACCOUNT"
m))))
dispatch)))
My reasoning
I would be tempted to answer that yes, the change is safe, for the following reason.
In the section Serializing access to shared state, page 304, I read the following (my emphasis)
> […] serialization creates distinguished sets of procedures such that only one execution of a procedure in each serialized set is permitted to happen at a time. […]
>
> We can use serialization to control access to shared variables. For example, if we want to update a shared variable based on the previous value of that variable, we put the access to the previous value of the variable and the assignment of the new value to the variable in the same procedure. We then ensure that no other procedure that assigns to the variable can run concurrently with this procedure by serializing all of these procedures with the same serializer. […]
From this, my understanding is that given one serializer (i.e. one of the objects/entities created via make-serializer
), all functions serialized via that one serializer belong to the same set, hence their operations cannot interleave with each other.
Therefore, since in the second program too, the (make-serializer)
call is made only once (for each call to (make-account some-balance)
), only one serializer exits in the whole program (for each…), and it goes by the name of protected
, so all functions that serializers serializes end up in the same set, and so they can't step on each other's feet.
Is this conclusion correct?
答案1
得分: 1
我相当肯定这个变化是安全的。特别是只要每个帐户只有一个序列化器,那就没问题。在修改后的make-account
过程中仍然如此:唯一的区别是,当你执行例如(account 'withdraw)
时,不再分配新的序列化器管理的过程集合的成员,而是重用之前创建的一个:你只是节省了一点分配开销,真的。
英文:
I am fairly sure that the change is safe. In particular so long as there is exactly one serializer per account you are OK. That remains true in the modified make-account
procedure: the only difference is that you're not allocating a new a member of the set of procedures that the serializer manages each time you say, for instance (account 'withdraw)
, but reusing one you made earlier: you just save a little allocation overhead, really.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论