Open mackstone opened 7 years ago
首先在同一个时刻,只会有一个线程执行这个Actor,所以当Actor继续被调度的时候,肯定可以观测到最新的状态哈. 因为这个状态属于这个Actor,而不属于某个线程.
状态可以是任何东西哈.
属于Actor不属于线程这个我没理解过来,可以说的更详细点吗?有相关知识点的资料吗?谢谢
Erlang 资料请看Erlang
就是说这个是ActorCell的一个字段而已
Refs
kerr我理解你说的意思了,actor内部状态的改变跟线程没关系,只跟actor自身有关;只要我不把这个内部状态暴露出去,那么对actor来说,怎么改变这个状态对actor自身来说都是可见的
在issues中提及的问题: “在时刻M1,Actor A1被线程T1所执行处理消息m0,内部状态S发生改变,假设S=1; 在时刻M2, Actor A1被线程T2所执行去处理消息m1, 此刻Actor A1必然能观察到S==1,而不会出现S的值在内存中不可见的问 题。” 在AKKA中的Actor模型能保证可见性的实现原理如下: 这个可见性是基于JMM 中happens-before规则实现(基于如下三种happens-before规则)的: 1.程序顺序规则:一个线程中每个操作,happens-before于该线程中的任意后续操作。 2.volatile变量规则:对于一个volatile域的写操作,happens-before于任意后续对这个volatile域的读。 3.传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
在akka中的Actor模型中,每个Actor实例在同一个时刻只有一个线程在调度(程序顺序规则的 happens-before);并且次Actor被调度执行message完毕后,都会修改当前Actor的一个volatile变量,代码如下:
final def run = {
try {
if (!isClosed) { //Volatile read, needed here
processAllSystemMessages() //First, deal with any system messages
processMailbox() //Then deal with messages
`}
}finally {
setAsIdle() //Volatile write, needed here
dispatcher.registerForExecution(this, false, false)
}
}
在finally{}中setAsIdle()方法是修改一个volatile变量
@tailrec
final def setAsIdle(): Boolean = {
val s = status
updateStatus(s, s & ~Scheduled) || setAsIdle()
}
方法processMailbox() 处理当前actor收到的message
@tailrec private final def processMailbox(
left: Int = java.lang.Math.max(dispatcher.throughput, 1),
deadlineNs: Long = if (dispatcher.isThroughputDeadlineTimeDefined == true) System.nanoTime + dispatcher.throughputDeadlineTime.toNanos else 0L): Unit =
if (shouldProcessMessage) {
val next = dequeue()
if (next ne null) {
if (Mailbox.debug) println(actor.self + " processing message " + next)
actor invoke next
if (Thread.interrupted())
throw new InterruptedException("Interrupted while processing actor messages")
processAllSystemMessages()
if ((left > 1) && ((dispatcher.isThroughputDeadlineTimeDefined == false) || (System.nanoTime - deadlineNs) < 0))
processMailbox(left - 1, deadlineNs)
}
}
在每次处理邮箱中的message之前if(shouldProcessMessage)都会获取一个vloatile的状态值
final def shouldProcessMessage: Boolean = (status & shouldNotProcessMask) == 0
那么在上面的代码片段中就是使用了一个volatile变量的写、读操作 的happens-before规则来实现happens-before的传递性,如图: 最终Actor模型保证了: “在时刻M1,Actor A1被线程T1所执行处理消息m0,内部状态S发生改变,假设S=1; 在时刻M2, Actor A1被线程T2所执行去处理消息m1, 此刻Actor A1必然能观察到S==1,而不会出现S的值在内存中不可见的问题”
“在时刻M1,Actor A1被线程T1所执行处理消息m0,内部状态S发生改变,假设S=1; 在时刻M2, Actor A1被线程T2所执行去处理消息m1, 此刻Actor A1必然能观察到S==1,而不会出现S的值在内存中不可见的问题。” 问题: 当前的S可以是对象吗?如果是对象那么Actor在AKKA中是如何来实现共享内存对象的可见性问题?