我是一个学习如何在Android上编码的模拟人,所以如果这个问题听起来很愚蠢,请耐心等待。
我理解同步的要点。如果我有两个线程可以访问和修改的数据,则可能导致两个线程中的数据变量中的值不一致。
使方法同步并将其锁定直到一个线程完成执行(执行任何条件检查)是有意义的,但为什么单个语句会有问题?对于多个语句来说这很重要,因为在一个语句中,线程1有可能在两个或多个语句之间走出runnable状态。但我不明白单个语句的重点是什么。
这是一个例子
如果我有一个可以从一个游戏线程调用的监听器,它会修改一个数据变量为什么我会这样做...
public void onCompletionListener(MediaPlayer player){
synchronized (this){
isPrepared = false;
}
}
我的Music类中还有另一种名为stop
的方法 public void stop(){
mediaPlayer.stop()
synchronized(this){
isPrepared = false;
}
}
为什么我要这么做呢?这样做是为了保证两个线程之间的值的一致性吗?如果可以,我可以使用像volatile这样的东西?会更好吗?
我问,因为我听说同步很昂贵。还有更好的选择吗?
先谢谢大家回答我的问题。我很感激。 编辑:我读了这个synchronization on single statement?
我想我明白了..如果有人可以详细说明那将是非常棒的。关于volatile是否是一个更好的替代方案,我最初的问题的第二部分也没有答案:)
答案 0 :(得分:4)
这样做是因为同步还对线程之间的内存可见性提出了要求。
如果该写入不是同步的或易失性的,那么对于其他线程何时可见,就没有任何硬性和快速的要求。另一个线程可能在其堆栈中有一个isPrepared
的副本,表示为true,它可以永远运行而不知道返回主内存并检查是否有其他人在没有同步或volatile的情况下更改了isPrepared
参考
volatile关键字将满足确保其他线程看到更新的直接要求。如果没有看到整个班级/系统是否可以接受,那就不可能说。可能存在其他同步方法,并且当其中一个是执行中期时更改isPrepared的状态是非法的。显然,删除同步以支持易失性引用将是错误的。
答案 1 :(得分:0)
在您的情况下,使用volatile on boolean也可以在没有同步的情况下工作 原始布尔值表示为4字节值,并将写入一个(汇编程序)语句。
对于8字节值(例如long / double)不能保证工作,其中一个线程可以写入低4字节,而另一个线程写入高4字节。
答案 2 :(得分:0)
作为对以前答案的补充,我想补充一点,在某些情况下,您的单行源代码可以转换为多行机器可执行代码,例如
计数器++
虽然它可能看起来像一个单独的操作,但表达式计数器++实际上是三个 单独的操作:
1)读取计数器的值
2)将此值加1
3)将更新后的值存储在计数器
中
因此,这种语句也应该在多线程上下文中同步。