TimurVI Asked:2020-02-09 19:04:47 +0800 CST2020-02-09 19:04:47 +0800 CST 2020-02-09 19:04:47 +0800 CST 哪些数据类型(线程)需要与多线程访问协调? 772 有实例变量、类变量、局部变量、字面量、引用类型、原始类型。 以下哪个(线程)需要协调多线程访问(通过同步块/方法使用)? java 2 个回答 Voted Uraty 2020-02-09T19:24:49+08:002020-02-09T19:24:49+08:00 你可能误解了同步块的本质。阅读 Race Conditional。简单举个例子,这种情况是当一个线程读取一个对象,已经读取了一半的对象然后bam,系统切换到另一个线程开始写入这个对象,完成写入到最后,然后再次切换到第一个线程,该线程完成读取已修改对象的后半部分。结果,对象被歪曲读取(旧状态的地板,新状态的地板)。 实际上,您的问题的答案是,只有在可能进行此类更改时才需要同步。这些是任何可变对象(不可变对象对此具有免疫力 - 如果对象无法更改,则不会存在竞争条件,因为它不能写入,只能读取),其中将发生更改(如果没有人更改对象,也就是说,它实际上是不可变的 - 您可以更改它,但没有人这样做,然后再次没有竞争情况)在不同的线程中(如果您不打算使用来自不同线程的对象,那么有考虑多线程毫无意义)。 Best Answer Nikolai 2020-02-09T19:58:07+08:002020-02-09T19:58:07+08:00 有实例变量、类变量、局部变量、字面量、引用类型、原始类型。 您将所有内容混合在一起:有几种类型的变量(实例、类、本地),每一种都可以是不同的类型——原始类型、对象引用。使用文字(String 类型的对象)与使用其他引用类型相同。 在多线程模式下工作时,有必要协调对共享资源的访问——很明显,局部变量不是这样的,它们的实例是为每个线程创建的。 使用类变量和实例变量时是否需要同步取决于您对它们的处理方式。例如,类变量通常是某种常量(static final)——基元或不可变对象,因此,它们的值在整个程序期间不会改变,也不需要同步访问它们。 如果执行了任何非原子修改(对类或实例变量无关紧要),则需要手动同步(或使用特殊类进行多线程工作 - 各种原子、并发集合等) . 让我们看一个简单的例子: private volatile int i = 0; // volatile, чтобы переменные не хранились в кэше и значения были одинаковы во всех потоках public int incrementAndGet(){ i = i + 1; return i; } 该方法incrementAndGet应将值i增加 1 并返回新值。但是,如果在 2 个线程中同时调用此方法,则该方法的结果是不可预测的:在每个线程中,它可以同时返回 1 和 2。这是由于递增操作是非原子的 (首先读取当前值,然后将 1 添加到其中,然后发生写入 - 在一个线程中的任何这些执行步骤中,另一个线程可以“嵌入”)。 为了解决这个问题,方法必须同步或者AtomicInteger使用java.util.concurrent.atomic.
你可能误解了同步块的本质。阅读 Race Conditional。简单举个例子,这种情况是当一个线程读取一个对象,已经读取了一半的对象然后bam,系统切换到另一个线程开始写入这个对象,完成写入到最后,然后再次切换到第一个线程,该线程完成读取已修改对象的后半部分。结果,对象被歪曲读取(旧状态的地板,新状态的地板)。
实际上,您的问题的答案是,只有在可能进行此类更改时才需要同步。这些是任何可变对象(不可变对象对此具有免疫力 - 如果对象无法更改,则不会存在竞争条件,因为它不能写入,只能读取),其中将发生更改(如果没有人更改对象,也就是说,它实际上是不可变的 - 您可以更改它,但没有人这样做,然后再次没有竞争情况)在不同的线程中(如果您不打算使用来自不同线程的对象,那么有考虑多线程毫无意义)。
您将所有内容混合在一起:有几种类型的变量(实例、类、本地),每一种都可以是不同的类型——原始类型、对象引用。使用文字(String 类型的对象)与使用其他引用类型相同。
在多线程模式下工作时,有必要协调对共享资源的访问——很明显,局部变量不是这样的,它们的实例是为每个线程创建的。
使用类变量和实例变量时是否需要同步取决于您对它们的处理方式。例如,类变量通常是某种常量(
static final
)——基元或不可变对象,因此,它们的值在整个程序期间不会改变,也不需要同步访问它们。如果执行了任何非原子修改(对类或实例变量无关紧要),则需要手动同步(或使用特殊类进行多线程工作 - 各种原子、并发集合等) . 让我们看一个简单的例子:
该方法
incrementAndGet
应将值i
增加 1 并返回新值。但是,如果在 2 个线程中同时调用此方法,则该方法的结果是不可预测的:在每个线程中,它可以同时返回 1 和 2。这是由于递增操作是非原子的 (首先读取当前值,然后将 1 添加到其中,然后发生写入 - 在一个线程中的任何这些执行步骤中,另一个线程可以“嵌入”)。为了解决这个问题,方法必须同步或者
AtomicInteger
使用java.util.concurrent.atomic
.