引用类型作为方法形参会产生线程安全问题吗?

2020-12-22 19:39:51 +08:00
 zhao1014

书中说不会产生

可是线程持有引用的副本,通过引用副本操作对象,应该是存在多线程同时操作同一个对象的情况啊,为什么不会有线程安全问题呢?

2230 次点击
所在节点    Java
11 条回复
Jooooooooo
2020-12-22 19:45:43 +08:00
具体什么问题?
zhao1014
2020-12-22 20:07:33 +08:00
@Jooooooooo
类似于这样?我不知道我举得这个例子对不对,抱歉。

书中原文是这样的:“对于局部变量(包括形式参数和方法体内定义的变量),由于不同的线程各自访问的是各自的那一份局部变量,因此局部变量的使用不会导致竞态!”

当时看到就有点疑惑,如果是引用类型,那不同线程操作的还是同一个对象吧。。

另外,PC 端怎么没有 Append 了,好奇怪。

public class Demo {

static class Number {
int count = 1;
}

public static void add(Number number) {
number.count += 1;
}

public static void main(String[] args) {
Number number = new Number();

for (int i = 0; i < 100; i++) {
new Thread() {
@Override
public void run() {
add(number);
}
}.start();
}
//结果不为 100
System.out.println(number.count);
}
}
zhao1014
2020-12-22 20:14:45 +08:00
原文的意思应该是:“即使对局部变量的操作是非原子性的,也不会导致线程安全问题”
kera0a
2020-12-22 20:27:52 +08:00
指针指向的那个对象,如果多个线程去修改会有线程安全问题。
但是你书里说的,局部变量没有

你方法内,用了一个变量存了这个对象的指针,你对这个变量进行操作是没问题的,你对这个变量里的值所指向的对象进行操作是有问题的
Zhuzhuchenyan
2020-12-22 20:31:38 +08:00
1. 即使正确执行预期输出应该是 101
2. 这里应该关注 += 操作是否是原子的
3. System.out.println 的调用时机在此处并不保证在所有 Thread 都完成之后
340244120w
2020-12-22 20:33:24 +08:00
形参本身就存一个引用,你对他的操作仅有改变其引用。比如形参一开始引用的 a,你方法里可以把他改成引用对象 b 。

而你理解的对象内部改变,是对实参的操作。
zhao1014
2020-12-22 20:34:51 +08:00
@kera0a 懂了,谢谢大佬
zhao1014
2020-12-22 20:39:24 +08:00
@Zhuzhuchenyan 确实是 101,我写错了(狗头); println 这里确实没注意,谢谢提醒;
@340244120w 看来我对形参和实参的概念理解的有问题,听你说的瞬间就明白了,感谢!
Takamine
2020-12-23 00:25:15 +08:00
这个也让我想到了 Java 是值传递的原因。
catcn
2020-12-23 08:29:08 +08:00
请把你二楼贴的代码敲上 20 遍
SkyLine7
2020-12-23 14:16:30 +08:00
栈封闭

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/737998

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX