JDK 原罪...

2017-02-23 16:56:14 +08:00
 skywayman

多线程开发是 Java 语言中经常用到的(别说你不用)....

当我们谈论多线程的时候总有一个讨论点 : 线程安全. 当我们谈论线程安全的时候我们在谈什么? 什么原子性\可见性\顺序性\锁\同步\CAS\xx 原则\volatile 语法\jdk 的新库\vector 与 arraylist 哪个安全\面试考题等等等等....

SO...

妈蛋,能不能先把 JDK 中成百上千个类中,哪些不是线程安全的给苦逼的程序员标注出来先? 原罪啊... 老司机都表示不淡定了...

6166 次点击
所在节点    程序员
48 条回复
mikulch
2017-02-24 00:02:25 +08:00
楼主之前写啥语言的。
ovear
2017-02-24 00:06:11 +08:00
@skywayman
线程安全是跟程序员的设计有关
并不是说类库在多线程情况下就一定有问题。而是可能出现意料外的情况,但是在正确的设计中,即使是多线程环境,一些所谓的非线程安全的类库也不会产生 意料外 的情况。而这时候编译器抛出 warning 就有点。。。了

所以这个属于业务逻辑问题,锅在程序员,跟编译器关系不大。
skywayman
2017-02-24 00:15:48 +08:00
@ovear 那什么是正确的设计?把线程安全的方方面面都全部搞懂后设计出来的程序就是正确的设计了?很多业务复杂的多线程环境,基础类库经常出现隐性的深层次问题,调起来非常的伤神.这个不否认吧. 我觉得出 warning 多好,即能淘汰旧 api,也能迫使开发人员知识体系升级,还减少出错,一举多得!
ovear
2017-02-24 00:24:04 +08:00
@skywayman 所以你也说了,这是“你觉得”

同步不是百利而无一害的,它是有代价的,这是由程序员自己决定的,是否使用读同步,写同步。这些都是有代价的。
打个比方,在外部条件的约束下,也许是多线程中使用非线程安全的类库,但是却能保证不出问题

再打个比方,一个数据结构中,多个线程共用,但是每个线程负责不同的部分。此时有使用读写同步的必要么。

诸如此类的情况太多了,这应该是程序员去关心的业务具体展示,而不是编译器关心你的算法
ovear
2017-02-24 00:28:38 +08:00
@ovear 而且更重要的是,所谓官方的线程安全,很可能跟你业务所需要的线程安全,是有差异的。类库的线程安全是不能实现你需要的效果的。
最简单的比方

public static void main(String[] args){
while(true){
for(int i = 0; i<10; i++){
vector.add(i);
}
}

//一个线程删数据
Thread removeThread = new Thread(new Runnable(){
@Override
public void run(){
for(int i=0 ; i<vector.size() ;i++){
vector.remove(i);
}
}
});

//一个线程读数据
Thread printThread = new Thread(new Runnable() {
@Override
public void run(){
for(int i=0 ; i<vector.size() ;i++){
System.out.println(vector.get(i));
}
}
});

removeThread.start();
printThread.start();

//防止过多线程,内存溢出
while(Thread.activeCount() > 20);
}


上述代码就会产生意料外的情况,那么 Vector 是非线程安全的么?


代码来自: https://zhuanlan.zhihu.com/p/21339889
zhuangzhuang1988
2017-02-24 00:58:08 +08:00
题主想法是好的
在 《 Java 并发编程实战》这本书中就大量使用了这个方法使用的是标注,附录中也有详细描述
bombless
2017-02-24 02:06:23 +08:00
经常是这样的:除非特别说明,都是线程不安全的。
来我们 rust 吧,仍然是除非特别说明都是线程不安全的。不过我们的线程安全在类型中被标出来了,因此编译器会检查一些情况,比如数据竞争。
des
2017-02-24 07:54:08 +08:00
@bombless 主要还是怕踩坑。好的设计当然是不用说的。
打比方来说 c 里面有个根据 DNS 获取 ip 的 API ,就有线程不安全版的,如果没有标注的话,就直接掉进去了,总不能所有东西都加锁吧?
Citrus
2017-02-24 08:02:48 +08:00
Citrus
2017-02-24 08:04:55 +08:00
@ovear 虽然你说的没错,但是感觉你有点曲解了楼主的意思ˊ_>ˋ感觉楼主只是想方便快捷的知道哪些是线程安全的哪些不是而已,这样就不用用个啥就提心吊胆的吧~
ob
2017-02-24 08:30:03 +08:00
@Citrus 用的时候,每个类的注释是有写的吧。
zacard
2017-02-24 09:16:25 +08:00
在多线程环境中,非线程安全的类不一定就有问题啊。。。。
ovear
2017-02-24 09:50:54 +08:00
@Citrus 自动完成以及提示
比如说 NetBeans 可以按住 ctrl 和类的名字看当前类的注释,一般线程安全和非线程安全都是用粗体字标记,应该已经够简单了吧=。=

我只是认为,这个操作不应该由编译器进行 warning
pangliang
2017-02-24 10:18:16 +08:00
楼主应该去写 rust
LINEX
2017-02-24 10:25:35 +08:00
只能慢慢适应。其实看一下源代码很快就可以判断是不是线程安全的嘛
skywayman
2017-02-24 10:43:13 +08:00
@Citrus 言简意赅,知音,哈哈
@ovear 示例没毛病,@Citrus 表达了我的意思,假如我是一个小白,先不管业务逻辑,代码中不是用的 vector,是用的 arraylist,如果编译器出警告说:在多线程环境中用 arraylist 不安全,建议切换 vector,同理 Integer 建议切换成 AtomicInteger 是否会更好?
@des 知音,哈哈.
@pangliang 有空了解一下.谢谢!
zhzy0077
2017-02-24 10:55:27 +08:00
可是编译器怎么知道你这个 ArrayList 会不会用在多线程环境中。。如果就用 ArrayList 存数据,不去修改的话,事实上这个 ArrayList 也是线程安全的,编译器也要告警应该用 Vector ?
jaxonHu
2017-02-24 10:59:29 +08:00
《多处理器编程的艺术》
sagaxu
2017-02-24 11:20:12 +08:00
没写安全的,就是不安全的,即时某个版本实现的安全,也可能随时改变。
WhoMercy
2017-02-24 11:43:02 +08:00
Junior Coder :这什么辣鸡编译器(IDE),怎么不把所有老司机约定成俗的东西都提示出来(我又不是老司机),使用的时候又不想看文档,也从不看源码,你不提示我怎么知道,是不是看我掉坑里很开心??
这辣鸡*DK ,你只要告诉我怎么用就好了嘛,最好再带上几个不同版本的业务示例。

开心就好

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

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

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

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

© 2021 V2EX