2010-05-15 36 views

Trả lời

15

Nếu bạn có nghĩa là làm tổ cú pháp, thì câu trả lời là nó phụ thuộc vào việc bên trong dosync sẽ chạy trên cùng một luồng như bên ngoài.

Trong Clojure, bất kỳ khi nào một khối dosync được nhập, giao dịch mới sẽ được bắt đầu nếu chưa chạy trên chủ đề này. Điều này có nghĩa rằng trong khi thực thi vẫn nằm trên một luồng đơn, các giao dịch bên trong có thể được cho là được các giao dịch bên ngoài phủ nhận; tuy nhiên nếu một số dosync chiếm một vị trí được lồng trong một cú pháp khác trong số dosync, nhưng sẽ xảy ra khi được khởi chạy trên một chuỗi mới, nó sẽ có một giao dịch mới cho chính nó.

Một ví dụ đó (hy vọng) minh họa những gì sẽ xảy ra:

user> (def r (ref 0)) 
#'user/r 
user> (dosync (future (dosync (Thread/sleep 50) (println :foo) (alter r inc))) 
       (println :bar) 
       (alter r inc)) 
:bar 
:foo 
:foo 
1 
user> @r 
2 

Các giao dịch "bên trong" thử lại sau in :foo; giao dịch "bên ngoài" không bao giờ cần phải khởi động lại. (Lưu ý rằng sau khi điều này xảy ra, chuỗi lịch sử của r được phát triển, vì vậy nếu biểu mẫu "lớn" dosync được đánh giá lần thứ hai, thì bên trong dosync sẽ không thử lại. Tất nhiên.)

Ngẫu nhiên, Mark Volkmann đã viết một bài báo tuyệt vời về Clojure's Software Transactional Memory; nó rất khuyến khích đọc cho bất cứ ai quan tâm đến việc đạt được cái nhìn sâu sắc vững chắc vào chi tiết của loại này.

+0

Tôi thích ví dụ này. –

+0

Tại sao bộ định tính "cú pháp"? Và cú pháp có ý nghĩa gì? Tôi là một lisper phổ biến và tôi quen với "lexically", như trong kết thúc các biến được lexically nhìn thấy: (let ((x 42)) (lambda() x)) vs động (tức là, bị ràng buộc trong ngăn xếp cuộc gọi một nơi nào đó). – kennytilton

Các vấn đề liên quan