这个问题与我所遇到的特定问题无关,而是我发现难以解决的问题。问题的上下文是球拍类和线程。考虑以下actor%
类,其中包含一个actor线程,一个在线程邮箱中对消息进行排队的方法,以及一个接收返回值的方法(它没有任何用处,只打印它)。
(struct message (source method values))
(define actor%
(class object%
(super-new)
(init-field
[actor-thread
(create-actor-thread this)])
(define/public (receive-message source method arguments)
(define message (message source method arguments))
(thread-send actor-thread message))
(define/public (receive-value value)
(displayln value))))
作为旁注,如果想要创建一个actor,他们必须首先创建一个子类来实现actor理解的某些消息(作为方法)。他们有一种机制来发送消息(例如(actor-send actor 'hello 'world)
,用于向行为actor
发送消息,调用带有参数hello
的方法world
。
所有actor都在自己的线程中运行,其定义如下。简而言之:它从一个线程的收件箱中获取一条消息,它获取源(一个actor),方法(一个符号)和一些值(一个列表),并dynamically sends它自己调用actor%
的实例化子类的适当方法。
(define (create-actor-thread self)
(thread
(lambda ()
(let actor-loop ()
;#####----- Receive message -----#####
(define message (thread-receive))
(define source (message-source message))
(define method (message-method message))
(define values (message-values message))
(define return-value (dynamic-send self method values))
(send source receive-value return-value)
(actor-loop)))))
我知道调用消息的主体是在新线程的上下文中处理的,但这对于actor的并发角度是如何工作的呢?同时,当actor线程正在做繁重的工作时,actor可以在线程的邮箱中保持排队消息。我无法解决的问题(或者可以找到合理的解释)是actor对象似乎存在于两个上下文中:原始上下文和actor线程的上下文。两者都可以访问同一个对象。是否有一种错误的并发感,或者是否有一些魔法让这一切都很好用?
答案 0 :(得分:2)
我无法解决的问题(或者可以找到合理的解释)是actor对象似乎生活在两个上下文中:原始上下文和actor线程的上下文。
actor对象本身只是堆上的一些数据。原始线程和您在actor对象初始化中创建的线程都访问对所有线程共享的同一堆上的同一对象的引用。
当您在actor线程中执行方法调用时,您实际上是从类方法表中获取对方法实现的引用并运行它。调用确实发生在不同的线程上下文中,但方法实现本身也是通过堆共享的。
结论:这不是魔术,它只是在线程之间使用共享内存。