java - 多个线程何时访问相同的代码?
问题描述
我的问题是:
- 默认情况下,Java 程序是否只创建 1 个线程?
- 如果是,并且如果我们创建一个多线程程序,多个线程何时访问 Java 对象的相同代码?
例如,我有一个带有 2 个方法的 Java 程序 - add() 和 sub()。在什么情况下 2 个或更多线程会运行 'add()' 方法?
代码不总是线程安全的,因为多个线程将访问不同的代码部分吗?
如果不是,请展示一个关注线程安全的示例程序。
解决方案
不要考虑“代码段”,要考虑数据所在的位置以及有多少线程正在访问该实际数据。
局部变量存在于它们正在使用的线程的堆栈中,并且是线程安全的,因为它们是每个线程的不同数据“容器”。
任何存在于堆上的数据,例如实例或静态字段,本质上都不是线程安全的,因为如果多个线程访问该数据,那么它们可能会发生争用。
我们可以变得更复杂,并讨论数据的真正位置,但这个基本解释应该让您对正在发生的事情有一个很好的了解。
下面的代码给出了一个由两个线程共享的实例的示例,在这种情况下,两个线程都在访问同一个数组列表,它指向堆中相同的数组数据容器。运行几次,你最终会看到失败。如果您注释掉其中一个线程,它每次都会正常工作,从 99 开始倒计时。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
new Thread(r).start();
new Thread(r).start();
}
public static class MyRunnable implements Runnable {
// imagine this list living out in the heap and both threads messing with it
// this is really just a reference, but the actual data is in the heap
private List<Integer> list = new ArrayList<>();
{ for (int i = 0; i < 100; i++) list.add(i); }
@Override public void run() {
while (list.size() > 0) System.out.println(list.remove(list.size() - 1));
}
}
}
推荐阅读
- r - MatchIt 与多个单元
- jquery - 如何跳出Jquery进行迭代
- vb.net - 如何在 Visual Studio (VB) 中仅将 Word 段落的一部分加粗
- html - 行数据的 Html 表格设计问题
- mule - 如何处理 http 连接器响应代码
- javascript - React Semantic UI:Table.Header Cell 未占用全宽
- tensorflow - 将 InMemoryEvaluatorHook 与 TPU 一起使用会引发异常
- azure - Azure JWT 令牌密钥轮换
- android - 当视图变大时,我如何正确地在constraintLayout(android)中使用相邻的2条链而不覆盖链?
- javascript - D3.js:在没有 d3.drag 的情况下获得平移平移而无需缩放