线程安全与实现

1.什么是线程安全

在一个进程中可能会有多个线程,多个线程访问同一个对象时,在主程序内不需要做任何同步操作,或者在调用方法内进行其他的协调操作,调用这个对象的结果行为都是正确的,此时这个对象就是线程安全的。

2.引起线程不安全的原因

对于线程间共享数据的更改操作会导致结果错误。

3.线程不安全的解决策略

使共享数据在多线程情况下保持正确的取值。

4.java中线程安全的类

  • Vector 
  • HashTable
  • ConcurrentHashMap
  • StringBuffer
  • Properties
  • Stack
  • .....

5.线程不安全的类

  • ArrayList 
  • LinkedList
  • HashMap
  • HashSet
  • TreeMap
  • TreeSet
  • StringBulider

对于Vector源码

   public synchronized void insertElementAt(E obj, int index) {
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        modCount++;
        final int s = elementCount;
        Object[] elementData = this.elementData;
        if (s == elementData.length)
            elementData = grow();
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = obj;
        elementCount = s + 1;
    }

    public synchronized void addElement(E obj) {
        modCount++;
        add(obj, elementData, elementCount);
    }

  
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

    public synchronized void removeAllElements() {
        final Object[] es = elementData;
        for (int to = elementCount, i = elementCount = 0; i < to; i++)
            es[i] = null;
        modCount++;
    }

vector许多操作都是加了synchronized修饰的,例如插入,增加,移除。

对于HashTable源码,

    public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

其他添加synchronized修饰的方法,size(),isEmpty(),keys()等等

对于ConcurrentHashMap

ConcurrentHashMap实现线程安全也是通过synchronized关键字来控制代码同步来实现的,不同于HashTable的是ConcurrentHashMap在线程同步上更加细分化,它不会像HashTable那样一把包揽的将所有数据都锁住,而是采用分段锁的思路。

对于ConcurrentHashMap和HashTable

HashTable和ConcurrentHashMap都是线程安全的容器。

  •   HashTable: 线程安全,效率和容器的大小成正比。容器数据量越大,效率越慢
  •   ConcurrentHashMap: 线程安全,效率相对于不如HashMap,但是和HashTable相比,效率得到很大的提升。

       综合考虑,如果使用线程安全容器,推荐使用ConcurrentHashMap

对于StringBuffer源码

    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

所有的方法也是使用synchronized修饰确保线程安全。

猜你喜欢

转载自blog.csdn.net/m0_57885354/article/details/126777173
今日推荐