1. 程式人生 > >synchronized與lock之間的效能比較

synchronized與lock之間的效能比較

1.關於兩者的實現的比較

A).一般認為synchronized關鍵字的實現是源自於像訊號量之類的執行緒同步機制,涉及到執行緒執行狀態的切換,在高併發狀態下,CPU消耗過多的時間線上程的排程上,從而造成了效能的極大浪費。然而真的如此麼? 

執行緒的狀態主要有一下五種,分別是新建狀態,就緒狀態,執行狀態,阻塞狀態,消亡狀態等5種狀態


B).lock實現原理則是依賴於硬體,現代處理器都支援CAS指令,所謂CAS指令簡單的來說Compare And Set,CPU迴圈執行指令直到得到所期望的結果,換句話來說就是當變數真實值不等於當前執行緒呼叫時的值的時候(說明其他執行緒已經將這個值改變),就不會賦予變數新的值

。這樣就保證了變數在多執行緒環境下的安全性。

然而,現實情況是當JDK版本高於1.6的時候,synchronized已經被做了CAS的優化:具體是這樣的,當執行到synchronized程式碼塊時,先對物件頭的鎖標誌位用lock cmpxchg的方式設定成“鎖住“狀態,釋放鎖時,在用lock cmpxchg的方式修改物件頭的鎖標誌位為”釋放“狀態,寫操作都立刻寫回主記憶體。JVM會進一步對synchronized時CAS失敗的那些執行緒進行阻塞操作(呼叫作業系統的訊號量)(此段來摘自別處)。也就是先CAS操作,不行的話繼而阻塞執行緒。

除此之外,系統環境,CPU架構,虛擬機器環境都會影響兩者的效能關係。

舉例如下

1).X86_64 cpu i7 4910mq @4.0ghz ,Windows10 64bit,JDK1.8 hotspot 64bit虛擬機器環境

測試程式碼

測試對某Map物件高併發下的讀寫執行緒安全測試 
測試對比有synchronized,ReadWriteLock,ConcurrentHashMap,

public class MapTest {

     private Map<Integer,String> map = new ConcurrentHashMap<>();

     private long starttime;

     private
AtomicInteger count = new AtomicInteger(t_count); private final static int t_count = 5000; private final static int rw_count = 10000; Runnable readrun = new Runnable() { @Override public void run() { int i = rw_count; while (i > 0){ map.get(i); i--; } System.out.println("read-mapsize="+map.size()); if(count.decrementAndGet() == 0) System.out.println("time="+ (System.currentTimeMillis() - starttime +"ms")); } }; Runnable writerun = new Runnable() { @Override public void run() { int i = rw_count; while (i > 0){ map.put(i,i+""); i--; } System.out.println("write-mapsize="+map.size()); if(count.decrementAndGet() == 0) System.out.println("time="+ (System.currentTimeMillis() - starttime + "ms")); } }; public void run(){ starttime = System.currentTimeMillis(); for(int i = 0;i < t_count/2;i ++){ new Thread(writerun).start(); new Thread(readrun).start(); } } }

HashMap 用synchronized重寫

public class SyncHashMap extends HashMap{

    @Override
    public Object get(Object key) {
        // TODO Auto-generated method stub
        synchronized (this) {
            return super.get(key);
        }
    }

    @Override
    public synchronized Object put(Object key, Object value) {
        // TODO Auto-generated method stub
        synchronized (this) {
            return super.put(key, value);
        }

    }

}

用讀寫鎖實現的Map代理類,有些粗糙,沒加try finally

public class SyncMapProxy<K,V> implements Map<K,V>{

    private Map<K,V> origin;
    private ReadWriteLock lock;

    public SyncMapProxy(Map<K, V> origin) {
        this.origin = origin;
        lock = new ReentrantReadWriteLock();
    }

    public static  <K,V> SyncMapProxy<K,V> SyncMap(Map<K,V> map){
        return new SyncMapProxy<K,V>(map);
    }

    @Override
    public void clear() {
        lock.writeLock().lock();
        origin.clear();
        lock.writeLock().unlock();
    }

    @Override
    public boolean containsKey(Object key) {
        lock.readLock().lock();
        boolean res = origin.containsKey(key);
        lock.readLock().unlock();
        return res;
    }

    @Override
    public boolean containsValue(Object value) {
        lock.readLock().lock();
        boolean res = origin.containsKey(value);
        lock.readLock().unlock();
        return res;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        lock.readLock().lock();
        Set<Entry<K, V>> res = origin.entrySet();
        lock.readLock().unlock();
        return res;
    }

    @Override
    public V get(Object key) {
        lock.readLock().lock();
        V res = origin.get(key);
        lock.readLock().unlock();
        return res;
    }

    @Override
    public boolean isEmpty() {
        return origin.isEmpty();
    }

    @Override
    public Set<K> keySet() {
        lock.readLock().lock();
        Set<K> res = origin.keySet();
        lock.readLock().unlock();
        return res;
    }

    @Override
    public V put(K key, V value) {
        lock.writeLock().lock();
        V v = origin.put(key, value);
        lock.writeLock().unlock();
        return v;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> map) {
        lock.writeLock().lock();
        origin.putAll(map);
        lock.writeLock().unlock();
    }

    @Override
    public V remove(Object key) {
        lock.writeLock().lock();
        V v = origin.remove(key);
        lock.writeLock().unlock();
        return v;
    }

    @Override
    public int size() {
        return origin.size();
    }

    @Override
    public Collection<V> values() {
        lock.readLock().lock();
        Collection<V> res = origin.values();
        lock.readLock().unlock();
        return res;
    }
}

相關推薦

synchronizedlock之間效能比較

1.關於兩者的實現的比較 A).一般認為synchronized關鍵字的實現是源自於像訊號量之類的執行緒同步機制,涉及到執行緒執行狀態的切換,在高併發狀態下,CPU消耗過多的時間線上程的排程上,從而造成了效能的極大浪費。然而真的如此麼?  執行緒的狀態主要有一下五種,

SynchronizedLock之間的哪些事兒

Synchronized 一、應用 對於普通同步方法,鎖是當前例項物件; 對於靜態同步方法,鎖是當前類的Class物件; 對於同步程式碼塊,鎖是Synchronized括號裡配置的物件。 二、實現原理 當前一個執行緒試圖訪問同步程式碼塊時,它首先必須

多執行緒的理解思路梳理 + synchronizedLock比較

多執行緒的理解思路梳理 + synchronized與Lock 的比較 理解多執行緒的根本:資源問題與鎖的物件 synchronized的理解 附1:生產者消費者實現程式碼 理解Threa

synchronizedLock的區別使用

oca http details detail fps syn blog amp 的區別 https://www.cnblogs.com/benshan/p/3551987.html https://www.cnblogs.com/nsw2018/p/5821738.htm

array_push $arr[]=$value 效能比較分析

本文簡要分析一下php中array_push與$arr[] = $value兩種將元素加入陣列末尾的方法的效能 1. array_push方法 array_push 方法,將一個或多個元素壓入陣列的末尾。array_push() 將array當成一個棧,並將傳入的變數壓入array的末尾。a

GrafanaKibana之間比較

我們生活在一個大資料的世界中,即使是一個小型的IT環境也會產生大量資料。一旦組織弄清楚了生成資料的各種資料來源,以及收集,處理和儲存資料的方法,下一步工作的重點就是分析。 分析方法會根據用例、使用的工具以及資料本身而有所不同,但是視覺化資料的步驟,無論是日誌,度量標準還是跟蹤,現在都被視

詳解synchronizedLock的區別使用

原文:https://blog.csdn.net/u012403290/article/details/64910926?utm_source=copy  引言: 昨天在學習別人分享的面試經驗時,看到Lock的使用。想起自己在上次面試也遇到了synchronized與Loc

Java多執行緒synchronized lock同步及交替列印

synchronized與 lock 區別 1)Lock不是Java語言內建的,synchronized是Java語言的關鍵字。Lock是一個介面,通過這個介面的實現類可以實現同步訪問; 2)採用synchronized不需要手動釋放鎖,當synchronized方法或者sync

HadoopSpark之間比較

原文連結:https://www.cnblogs.com/yjd_hycf_space/p/7681535.html Hadoop框架的主要模組包括如下: Hadoop Common Hadoop分散式檔案系統(HDFS) Hadoop YARN Hadoo

MapList查詢效能比較

@Test  public void mapTest(){   /*    * 比較順序查詢和雜湊查詢的效能    */   //建立線性表集合   List<String> list=    new ArrayList<String>();   /

指標引用的效能比較

我們先來看一下傳指標與傳引用的效率方面的對比吧 本質上來說了,傳引用是一個變數的別名而已。並沒有開闢新的空間。而指標了是指向一個空間對應一個空間的地址 好吧,我們分別通過兩者效率,和本質方面看一下兩者之間的區別吧。 -首先看一下兩者的效率 看程式碼 #inclu

propertiesyml之間比較

兩種 als ati try 錯誤 spring 否則 register 並且 在Spring Cloud的配置文件中,發現使用yml與properties兩種後綴的文件: 在application.properties中內容是這樣的: server.port=8801eu

java多執行緒之synchronizedlock、waitnotify

class Res { public String name; public String sex; public Boolean flag = false; public Lock lock = new ReentrantLock(); Condition condition = lock.new

Python基礎入門:ListTuple、DictSet之間比較

定義方式: L=[1,2,3] T=('a','b',['A','B']) D={key:value,} S=(['a','b','c']) 比較:list與tuple皆為有序,dict與set為無序 因此dict與set不能通過下標序號呼叫,沒有append(),ins

ArrayListLinkedList、TreeSetHashSet、HashMapLinkedHashMap之間比較

前言:人類一思考,上帝就發笑 之前ArrayList與LinkedList、TreeSet與HashSet、HashMap與LinkedHashMap之間都比較茫然,下面我針對這 幾個類具體類來進行比較,首先我們上一張圖 在上面的比較中,我們針對相同顏色的倆者分別來進行

docker虛擬機器效能比較

概要 docker是近年來新興的虛擬化工具,它可以和虛擬機器一樣實現資源和系統環境的隔離。本文將主要根據IBM發表的研究報告,論述docker與傳統虛擬化方式的不同之處,並比較物理機、docker容器、虛擬機器三者的效能差異及差異產生的原理。

synchronized Lock

    關於同步,以前如果碰到了多執行緒的問題,那麼首先想到的是synchronized 關鍵字,給方法,或者程式碼塊加上synchronized,但是synchronized也有不少缺點,比如它釋放鎖只有兩個條件:1.程式正常結束,鎖被釋放2.程式發生異常,鎖被釋放。除了

synchronizedLock有什麼異同

Java語言提供了兩種鎖機制來實現對某個共享資源的同步:synchronized和Lock.其中synchronized使用Object物件本身的nofify、wait、nofityAll排程機制,而Lock可以使用Condition進行執行緒之間的排程,完成synchro

原生ServletSpring Controller效能比較

  在實際專案工作,有同事提出,Java原生的Servlet效能(響應速度與併發數)要比封裝過的Spring Controller高,基於這點,樓主用Apache的ab工具,對兩個簡單的應用做1000併發壓力測試,檢視兩者的響應速度與併發數、平均響應時間等引數。 原生

synchronizedLock的區別

util 可重入 方法 ted ace ber get ner ack 兩者區別: 1.首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類; 2.synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖; 3.