咋理解集合中线程安全和不安全的问题

线程安全这个问题不单单存在于集合类,其他的类里面也有,比如StringBuilder和StringBuffer。简单地说,你看一个类里面每个方法都加了synchronized修饰符,那它就是线程安全的。既然类里面每一个操作都加了线程同步操作,那么在外面就不用再写synchronized了。比如Vector和ArrayList,二者唯一的区别就是Vector每个方法都自带同步机制。这样的话,比如我要往集合里面加一个元素,又要保证多个线程不会同时调用同一个对象的add()方法,ArrayList里面就要酱紫写:ArrayList\u0026lt;String\u0026gt; list = new ArrayList\u0026lt;\u0026gt;();synchronized (list) { list.add("233");}而Vector里面只要酱紫写就行了:Vector\u0026lt;String\u0026gt; list = new Vector\u0026lt;\u0026gt;();list.add("233");为什么?因为ArrayList的add方法是酱紫定义的:public boolean add(E object) { ...}而Vector的add方法是酱紫定义的:public synchronized boolean add(E object) { .....}所以同样调用add()方法,对Vector对象再加synchronized就是多此一举。
■网友
楼上大神各抒己见,我来补充
存在线程安全问题必须满足三个条件:
1.有共享变量
2.处在多线程环境下
3.共享变量有修改操作。
所谓解决线程安全问题无非就是将操作原子化,正如楼上各位所说的加sychronized,或者加lock什么的,只要将操作原子化就能避免线程安全的问题。但加锁会有性能问题。
所以在多线程情况下,优先考虑能否不用共享,优先使用局部变量代替共享的全局变量。
只能用共享变量的时候优先使用原子类,诸如AtomicInteger尔尔。
没有原子类,可以自己创造自己的原子类。
如以上方法都不能奏效,再考虑使用sychro,lock之类尔尔。
别一上来就sychro,不仅low,而且显的不够专业

■网友
线程安全,就是集合里面的元素可以随便任意多个人同时读写,不会出问题;线程不安全就是不能多个人随便一起操作会乱套的
■网友
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
=================================================================
概念:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
安全性:
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。


推荐阅读