从一道题看线程安全
Java中的线程安全是什么:
就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问。
什么叫线程安全:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
看过vector源码的同学就会知道他的许多操作都是加了synchronized修饰的比如他的添加元素。(不知道synchronized是什么意思的自行百度!)synchronized就具有使每个线程依次排队操作共享变量的功能。
1 public synchronized void addElement(E obj) { modCount++; 2 ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; 3 }
而HashMap的所有操作都没有加synchronized修饰 ,不如他的put源码
1 public V put(K key, V value) { 2 if (key == null) 3 return 4 putForNullKey(value); 5 int hash = hash(key.hashCode()); 6 int i = indexFor(hash, table.length); 7 for(Entry<K,V> e = table[i]; e != null; e = e.next) { 8 Object k; 9 if (e.hash == hash &&((k = e.key) == key || key.equals(k))) { 10 V oldValue = e.value; 11 e.value = value; 12 e.recordAccess(this); 13 return 14 oldValue; } 15 } 16 modCount++; 17 addEntry(hash, key, value, i); 18 return null; 19 }
再看看ArrayList的add方法的源码
1 public boolean add(E e) { 2 ensureCapacity(size + 1); // Increments modCount!! 3 elementData[size++] = e; 4 return true; 5 }
再看StringBuffer的append源码,他是有synchronized修饰的
1 public synchronized 2 StringBuffer append(String str) { 3 super.append(str); 4 return this; 5 }
最后是Properties的setProperty方法,他是有synchronized修饰的
1 public synchronized 2 Object setProperty(String key, String value) { 3 return 4 put(key, value); 5 }
由此就可以判断出谁是线程安全的了。