1

我是一个模拟人,学习如何在 android 上编码,所以如果这个问题听起来很愚蠢,请多多包涵。

我了解同步的要点。如果我有两个线程可以访问和修改的数据,则可能导致两个线程中数据变量的值不一致。

使方法同步并锁定它们直到一个线程完成执行它(执行任何条件检查)是有意义的,但是为什么它对单个语句很重要?这对多个语句很重要,因为线程一个有可能在 2 个或多个语句之间退出可运行状态,但我不明白单个语句的意义何在。

这是一个例子

如果我有一个可以被调用的监听器,比如说一个游戏线程,它会修改一个数据变量,我为什么要这样做......

    public void onCompletionListener(MediaPlayer player){
    synchronized (this){
        isPrepared = false;
       }
    }

我的音乐课中还有另一种方法叫停止

   public void stop(){
   mediaPlayer.stop()
    synchronized(this){
    isPrepared = false;
       }
    }

我为什么要费心去做这件事?这样做是为了两个线程之间值的一致性吗?如果是这样,我可以使用 volatile 之类的东西吗?那会更好吗?

我问是因为我听说同步很昂贵。有更好的选择吗?

提前感谢大家回答我的问题。我很感激。编辑:我在单个语句上阅读了此同步?

我想我理解..如果有人能详细说明那将是很棒的。我最初关于 volatile 是否是更好的选择的问题的第二部分也没有得到解答:)

4

3 回答 3

4

之所以这样做,是因为同步还对线程之间的内存可见性提出了要求。

如果该写入不是同步的或易失的,那么对于其他线程何时可以看到它没有任何硬性要求。另一个线程可能在其堆栈中有一个副本为isPreparedtrue,并且它可以永远运行而无需返回主内存并检查是否其他人已更改isPrepared,如果没有同步或易失性引用。

volatile 关键字将满足确保其他线程看到更新的直接要求。如果没有看到整个班级/系统,就不可能说它是否是可接受的替代品。可能还有其他同步方法,并且在其中一个处于执行中期时更改 isPrepared 的状态是非法的。显然,删除同步以支持易失性引用将是错误的。

于 2013-01-07T01:40:11.577 回答
0

在您的情况下,在布尔值上使用 volatile 也可以在没有同步的情况下工作。
原始布尔值表示为 4 字节值,并将写入一个(汇编程序)语句中。

这并不保证适用于 8 字节值(例如 long / double),其中一个线程可以写入较低的 4 个字节,而另一个线程可以写入较高的 4 个字节。

于 2013-01-07T01:36:05.163 回答
0

作为对先前答案的补充,我想补充一点,在某些情况下,您的单行源代码可以转换为多行机器可执行代码,例如

计数器++

尽管它可能看起来像一个单独的操作,但表达式 counter++ 实际上是三个独立的操作:

1) 读取计数器的值

2) 将此值加 1

3) 将更新后的值存储在计数器中

因此,这种语句也应该在多线程上下文中同步。

于 2016-07-12T10:06:52.610 回答