zoukankan      html  css  js  c++  java
  • Map 四种同步方式的性能比较

     

    如果需要使 Map 线程安全,大致有这么四种方法:

    1、使用 synchronized 关键字,这也是最原始的方法。代码如下


    Java代码 
    synchronized(anObject)  
    {  
        value = map.get(key);  
    }  
    Java代码 
    synchronized(anObject)  
    {  
        value = map.get(key);  

    synchronized(anObject)
    {
     value = map.get(key);
    }


    JDK1.2 提供了 Collections.synchronizedMap(originMap) 方法,同步方式其实和上面这段代码相同。

    2、使用 JDK1.5 提供的锁(java.util.concurrent.locks.Lock)。代码如下


    Java代码 
    lock.lock();  
    value = map.get(key);  
    lock.unlock();  
    Java代码 
    lock.lock();  
    value = map.get(key);  
    lock.unlock(); 

    lock.lock();
    value = map.get(key);
    lock.unlock();


    3、实际应用中,可能多数操作都是读操作,写操作较少。针对这种情况,可以使用 JDK1.5 提供的读写锁(java.util.concurrent.locks.ReadWriteLock)。代码如下


    Java代码 
    rwlock.readLock().lock();  
    value = map.get(key);  
    rwlock.readLock().unlock();  
    Java代码 
    rwlock.readLock().lock();  
    value = map.get(key);  
    rwlock.readLock().unlock(); 

    rwlock.readLock().lock();
    value = map.get(key);
    rwlock.readLock().unlock();


    这样两个读操作可以同时进行,理论上效率会比方法 2 高。

    4、使用 JDK1.5 提供的 java.util.concurrent.ConcurrentHashMap 类。该类将 Map 的存储空间分为若干块,每块拥有自己的锁,大大减少了多个线程争夺同一个锁的情况。代码如下


    Java代码 
    value = map.get(key); //同步机制内置在 get 方法中  
    Java代码 
    value = map.get(key); //同步机制内置在 get 方法中 

    value = map.get(key); //同步机制内置在 get 方法中

    写了段测试代码,针对这四种方式进行测试,结果见附图。测试内容为 1 秒钟所有 get 方法调用次数的总和。为了比较,增加了未使用任何同步机制的情况(非安全!)。理论上,不同步应该最快。

    我的 CPU 是双核的(Core 2 Duo E6300),因此太多线程也没啥意义,所以只列出了单线程、两个线程和五个线程的情况。更多线程时,CPU 利用率提高,但增加了线程调度的开销,测试结果与五个线程差不多。

    从附图可以看出:

    1、不同步确实最快,与预期一致。
    2、四种同步方式中,ConcurrentHashMap 是最快的,接近不同步的情况。
    3、synchronized 关键字非常慢,比使用锁慢了两个数量级。真是大跌眼镜,我很迷惑为什会 synchronized 慢到这个程度。
    4、使用读写锁的读锁,比普通所稍慢。这个比较意外,可能硬件或测试代码没有发挥出读锁的全部功效。

    结论:

    1、如果 ConcurrentHashMap 够用,则使用 ConcurrentHashMap。
    2、如果需自己实现同步,则使用 JDK1.5 提供的锁机制,避免使用 synchronized 关键字。

    描述: 多个线程每秒 Map.get 的执行次数之和
    大小: 28.8 KB
    测试代码。只图方便了,不大 OO,见笑。


    Java代码 
    import java.util.*;  
    import java.util.concurrent.*;  
    import java.util.concurrent.locks.*;  
     
    public class MapTest  
    {  
        public static final int THREAD_COUNT = 1;  
        public static final int MAP_SIZE = 1000;  
        public static final int EXECUTION_MILLES = 1000;  
        public static final int[] KEYS = new int[100];   
          
        public static void main(String[] args) throws Exception  
        {  
            //初始化  
            Random rand = new Random();  
            for (int i = 0; i < KEYS.length; ++i)  
            {  
                KEYS[i] = rand.nextInt();  
            }  
                      
            //创建线程  
            long start = System.currentTimeMillis();  
            Thread[] threads = new Thread[THREAD_COUNT];  
            for (int i = 0; i < THREAD_COUNT; ++i)  
            {  
                //threads[i] = new UnsafeThread();  
                //threads[i] = new SynchronizedThread();  
                //threads[i] = new LockThread();  
                //threads[i] = new ReadLockThread();  
                threads[i] = new ConcurrentThread();  
                threads[i].start();  
            }  
              
            //等待其它线程执行若干时间  
            Thread.sleep(EXECUTION_MILLES);  
     
            //统计 get 操作的次数  
            long sum = 0;         
            for (int i = 0; i < THREAD_COUNT; ++i)  
            {  
                sum += threads[i].getClass().getDeclaredField("count").getLong(threads[i]);  
            }  
            long millisCost = System.currentTimeMillis() - start;  
            System.out.println(sum + "(" + (millisCost) + "ms)");  
            System.exit(0);  
        }  
          
        public static void fillMap(Map<Integer, Integer> map)  
        {  
            Random rand = new Random();  
              
            for (int i = 0; i < MAP_SIZE; ++i)  
            {  
                map.put(rand.nextInt(), rand.nextInt());  
            }  
        }  
    }  
     
    class UnsafeThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        public long count = 0;    
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                map.get(MapTest.KEYS[index]);  
                ++count;  
            }  
        }  
    }  
     
    class SynchronizedThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                synchronized(SynchronizedThread.class)  
                {  
                    map.get(MapTest.KEYS[index]);  
                }  
                ++count;  
            }  
        }  
    }  
     
    class LockThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        private static Lock lock = new ReentrantLock();  
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                lock.lock();  
                map.get(MapTest.KEYS[index]);  
                lock.unlock();  
                ++count;  
            }  
        }  
    }  
     
    class ReadLockThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        private static Lock lock = new ReentrantReadWriteLock().readLock();  
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                lock.lock();  
                map.get(MapTest.KEYS[index]);  
                lock.unlock();  
                ++count;  
            }  
        }  
    }  
     
    class ConcurrentThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>();     
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                map.get(MapTest.KEYS[index]);  
                ++count;  
            }  
        }  
    }  
    Java代码 
    import java.util.*;  
    import java.util.concurrent.*;  
    import java.util.concurrent.locks.*;  
     
    public class MapTest  
    {  
        public static final int THREAD_COUNT = 1;  
        public static final int MAP_SIZE = 1000;  
        public static final int EXECUTION_MILLES = 1000;  
        public static final int[] KEYS = new int[100];   
          
        public static void main(String[] args) throws Exception  
        {  
            //初始化  
            Random rand = new Random();  
            for (int i = 0; i < KEYS.length; ++i)  
            {  
                KEYS[i] = rand.nextInt();  
            }  
                      
            //创建线程  
            long start = System.currentTimeMillis();  
            Thread[] threads = new Thread[THREAD_COUNT];  
            for (int i = 0; i < THREAD_COUNT; ++i)  
            {  
                //threads[i] = new UnsafeThread();  
                //threads[i] = new SynchronizedThread();  
                //threads[i] = new LockThread();  
                //threads[i] = new ReadLockThread();  
                threads[i] = new ConcurrentThread();  
                threads[i].start();  
            }  
              
            //等待其它线程执行若干时间  
            Thread.sleep(EXECUTION_MILLES);  
     
            //统计 get 操作的次数  
            long sum = 0;         
            for (int i = 0; i < THREAD_COUNT; ++i)  
            {  
                sum += threads[i].getClass().getDeclaredField("count").getLong(threads[i]);  
            }  
            long millisCost = System.currentTimeMillis() - start;  
            System.out.println(sum + "(" + (millisCost) + "ms)");  
            System.exit(0);  
        }  
          
        public static void fillMap(Map<Integer, Integer> map)  
        {  
            Random rand = new Random();  
              
            for (int i = 0; i < MAP_SIZE; ++i)  
            {  
                map.put(rand.nextInt(), rand.nextInt());  
            }  
        }  
    }  
     
    class UnsafeThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        public long count = 0;    
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                map.get(MapTest.KEYS[index]);  
                ++count;  
            }  
        }  
    }  
     
    class SynchronizedThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                synchronized(SynchronizedThread.class)  
                {  
                    map.get(MapTest.KEYS[index]);  
                }  
                ++count;  
            }  
        }  
    }  
     
    class LockThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        private static Lock lock = new ReentrantLock();  
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                lock.lock();  
                map.get(MapTest.KEYS[index]);  
                lock.unlock();  
                ++count;  
            }  
        }  
    }  
     
    class ReadLockThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();   
        private static Lock lock = new ReentrantReadWriteLock().readLock();  
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                lock.lock();  
                map.get(MapTest.KEYS[index]);  
                lock.unlock();  
                ++count;  
            }  
        }  
    }  
     
    class ConcurrentThread extends Thread  
    {  
        private static Map<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>();     
        public long count = 0;  
          
        static 
        {  
            MapTest.fillMap(map);  
        }  
          
        public void run()  
        {  
            for (;;)  
            {  
                int index = (int)(count % MapTest.KEYS.length);  
                map.get(MapTest.KEYS[index]);  
                ++count;  
            }  
        }  

    import java.util.*;
    import java.util.concurrent.*;
    import java.util.concurrent.locks.*;

    public class MapTest
    {
     public static final int THREAD_COUNT = 1;
     public static final int MAP_SIZE = 1000;
     public static final int EXECUTION_MILLES = 1000;
     public static final int[] KEYS = new int[100];
     
     public static void main(String[] args) throws Exception
     {
      //初始化
      Random rand = new Random();
      for (int i = 0; i < KEYS.length; ++i)
      {
       KEYS[i] = rand.nextInt();
      }
        
      //创建线程
      long start = System.currentTimeMillis();
      Thread[] threads = new Thread[THREAD_COUNT];
      for (int i = 0; i < THREAD_COUNT; ++i)
      {
       //threads[i] = new UnsafeThread();
       //threads[i] = new SynchronizedThread();
       //threads[i] = new LockThread();
       //threads[i] = new ReadLockThread();
       threads[i] = new ConcurrentThread();
       threads[i].start();
      }
      
      //等待其它线程执行若干时间
      Thread.sleep(EXECUTION_MILLES);

      //统计 get 操作的次数
      long sum = 0;  
      for (int i = 0; i < THREAD_COUNT; ++i)
      {
       sum += threads[i].getClass().getDeclaredField("count").getLong(threads[i]);
      }
      long millisCost = System.currentTimeMillis() - start;
      System.out.println(sum + "(" + (millisCost) + "ms)");
      System.exit(0);
     }
     
     public static void fillMap(Map<Integer, Integer> map)
     {
      Random rand = new Random();
      
      for (int i = 0; i < MAP_SIZE; ++i)
      {
       map.put(rand.nextInt(), rand.nextInt());
      }
     }
    }

    class UnsafeThread extends Thread
    {
     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
     public long count = 0; 
     
     static
     {
      MapTest.fillMap(map);
     }
     
     public void run()
     {
      for (;;)
      {
       int index = (int)(count % MapTest.KEYS.length);
       map.get(MapTest.KEYS[index]);
       ++count;
      }
     }
    }

    class SynchronizedThread extends Thread
    {
     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
     public long count = 0;
     
     static
     {
      MapTest.fillMap(map);
     }
     
     public void run()
     {
      for (;;)
      {
       int index = (int)(count % MapTest.KEYS.length);
       synchronized(SynchronizedThread.class)
       {
        map.get(MapTest.KEYS[index]);
       }
       ++count;
      }
     }
    }

    class LockThread extends Thread
    {
     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
     private static Lock lock = new ReentrantLock();
     public long count = 0;
     
     static
     {
      MapTest.fillMap(map);
     }
     
     public void run()
     {
      for (;;)
      {
       int index = (int)(count % MapTest.KEYS.length);
       lock.lock();
       map.get(MapTest.KEYS[index]);
       lock.unlock();
       ++count;
      }
     }
    }

    class ReadLockThread extends Thread
    {
     private static Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
     private static Lock lock = new ReentrantReadWriteLock().readLock();
     public long count = 0;
     
     static
     {
      MapTest.fillMap(map);
     }
     
     public void run()
     {
      for (;;)
      {
       int index = (int)(count % MapTest.KEYS.length);
       lock.lock();
       map.get(MapTest.KEYS[index]);
       lock.unlock();
       ++count;
      }
     }
    }

    class ConcurrentThread extends Thread
    {
     private static Map<Integer, Integer> map = new ConcurrentHashMap<Integer, Integer>(); 
     public long count = 0;
     
     static
     {
      MapTest.fillMap(map);
     }
     
     public void run()
     {
      for (;;)
      {
       int index = (int)(count % MapTest.KEYS.length);
       map.get(MapTest.KEYS[index]);
       ++count;
      }
     }
    }

    大小: 28.8 KB
     

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 黑色星期五
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    控件动态产生器(使用RegisterClasses提前进行注册)
    Delphi编写自定义控件以及接口的使用(做了一个TpgDbEdit)
    Log4delphi使用心得
  • 原文地址:https://www.cnblogs.com/zqmingok/p/2013794.html
Copyright © 2011-2022 走看看