首頁  >  文章  >  Java  >  java並發程式設計(4)效能與可擴展性

java並發程式設計(4)效能與可擴展性

巴扎黑
巴扎黑原創
2017-06-26 09:14:181460瀏覽

效能與可擴展性

一、Amdahl定律

1.問題與資源的關係

    在某些問題中,資源越多解決速度越快;而有些問題則相反:

  注意:每個程式中必然有串列的部分,而合理的分析出串列和並行的部分對程式的影響極大;串列部分佔比與多核心執行效率之間是指數級的關係

2.ConcurrentLinkedQueue

  在多核心環境中,這個執行緒安全的佇列比透過synchronizedList產生的佇列速度快很多

  可以說:concurrent中提供的類,比通過方法生成的線程安全類速度要快

二、線程開銷

  由於多線程有開銷:所以使用多執行緒必須確保效能的提升>並發的開銷

  上下文切換的開銷

  記憶體同步的開銷

#三、減少鎖定的競爭

  1.減少鎖定持有時間:縮小鎖的範圍

private final Map<String, String> attributes = new HashMap<String, String>();//整个方法上锁public synchronized boolean userLocationMatches(String name, String regexp) {
        String key = "users." + name + ".location";
        String location = attributes.get(key);if (location == null)return false;elsereturn Pattern.matches(regexp, location);
    }public boolean userLocationMatches(String name, String regexp) {
        String key = "users." + name + ".location";
        String location;//只针对可变状态上锁synchronized (this) {
            location = attributes.get(key);
        }if (location == null)return false;elsereturn Pattern.matches(regexp, location);
    }

 

  2.降低鎖定的請求頻率:鎖定分解、鎖定分段. ..

    鎖分解:將一個鎖分解為多個鎖如:無需在一​​個原子操作中更新多個狀態變量,每個狀態變量卻用的是同一個類鎖,就沒必要,每個不相干的狀態變數的使用自己的鎖定就行

public class ServerStatusBeforeSplit {public final Set<String> users;public final Set<String> queries;public ServerStatusBeforeSplit() {
        users = new HashSet<String>();
        queries = new HashSet<String>();
    }//每个方法使用 当前class实例锁,类似于synchronized(this),不管是否是操作同一共享状态public synchronized void addUser(String u) {
        users.add(u);
    }public synchronized void addQuery(String q) {
        queries.add(q);
    }public synchronized void removeUser(String u) {
        users.remove(u);
    }public synchronized void removeQuery(String q) {
        queries.remove(q);
    }
}public class ServerStatusAfterSplit {public final Set<String> users;public final Set<String> queries;//操作同一 状态的方法 使用相同的锁public ServerStatusAfterSplit() {
        users = new HashSet<String>();
        queries = new HashSet<String>();
    }public void addUser(String u) {synchronized (users) {
            users.add(u);
        }
    }public void addQuery(String q) {synchronized (queries) {
            queries.add(q);
        }
    }public void removeUser(String u) {synchronized (users) {
            users.remove(u);
        }
    }public void removeQuery(String q) {synchronized (users) {
            queries.remove(q);
        }
    }
}

 

  

  鎖定分段:如將map桶分成不同的段,每個段都有一個鎖,這樣,在執行某些操作如get,就可以持有不同的鎖從而提高並發效率,當然有些操作需要同時持有容器所有段的鎖如clear等

//Map分段锁实现public class StripedMap {// Synchronization policy: buckets[n] guarded by locks[n%N_LOCKS]private static final int N_LOCKS = 16;  //锁数量private final Node[] buckets;           //容器桶private final Object[] locks;           //同步监听器对象数组private static class Node {
        Node next;
        Object key;
        Object value;
    }public StripedMap(int numBuckets) {
        buckets = new Node[numBuckets];
        locks = new Object[N_LOCKS];for (int i = 0; i < N_LOCKS; i++)
            locks[i] = new Object();
    }private final int hash(Object key) {return Math.abs(key.hashCode() % buckets.length);
    }public Object get(Object key) {int hash = hash(key);//获取当前 key对应的index区域的锁,只获取了一个锁synchronized (locks[hash % N_LOCKS]) {for (Node m = buckets[hash]; m != null; m = m.next)if (m.key.equals(key))return m.value;
        }return null;
    }public void clear() {for (int i = 0; i < buckets.length; i++) {//获取 每个i对应的锁,就是获取了整个容器所有的分段锁synchronized (locks[i % N_LOCKS]) {
                buckets[i] = null;
            }
        }
    }
}

 

 

  3.避免熱點域

    熱點資源的鎖定競爭激烈,導致的效能問題

#  44 .替代獨佔鎖

    如:讀-寫鎖:讀讀可並行,來防止獨佔;使用原子狀態量;使用並發容器;使用不可變對像等

  5.減少上下文切換

    任務在阻塞於非阻塞的狀態中切換,就類似於一次上下文切換

    如:日誌,日誌的列印和IO操作會導致大量的阻塞和釋放,導致效能問題

 

以上是java並發程式設計(4)效能與可擴展性的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn