精华内容
下载资源
问答
  • 题目描绘 我们正在5个dubbo接心并收举行测试,统共线程数是64个,一直的挪用那些接心。视察到的非常浮现是TPS动摇较大,时下时低。 我们视察线程的运转状态是如许] 1.问题描述 我们在5个dubbo接口并发进行...
    [摘要:1.题目描绘 我们正在对5个dubbo接心并收举行测试,统共线程数是64个,一直的挪用那些接心。视察到的非常浮现是TPS动摇较大,时下时低。 我们视察线程的运转状态是如许]
    

    1.问题描述
    我们在对5个dubbo接口并发进行测试,总共线程数是64个,不停的调用这些接口。观察到的异常显现是TPS波动较大,时高时低。

    我们观察线程的运行状况是这样的:

    上图红色部分是线程阻塞的情况。

    我们查看线程栈的信息发现有20多个用户线程处于Blocked状态,blocked状态的代码如下:

    "DubboServerHandler-192.168.183.17:20880-thread-200" daemon prio=10 tid=0x00007fc0e802b800 nid=0x6a8f waiting for monitor entry [0x00007fbf25bda000]
    java.lang.Thread.State: BLOCKED (on object monitor)
    at com.jd.com.caucho.hessian.io.SerializerFactory.getSerializer(SerializerFactory.java:164)
    - locked <0x00000000c35af008> (a java.util.HashMap)
    at com.alibaba.com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:406)
    at com. alibaba.com.caucho.hessian.io.CollectionSerializer.writeObject(CollectionSerializer.java:102)
    at com. alibaba.com.caucho.hessian.io.Hessian2Output.writeObject(Hessian2Output.java:408)
    at com. alibaba.com.caucho.hessian.io.JavaSerializer$FieldSerializer.serialize(JavaSerializer.java:313)



    这说明如果该服务在该并发下还是会出现用户线程阻塞在代码

    at com.alibaba.com.caucho.hessian.io.SerializerFactory.getSerializer(SerializerFactory.java:164)处的情况,对于服务的稳定性和TPS都会造成一定的影响。
    2.问题分析
    根据上述日志的分析,我们定位到了线程锁部分的代码,我们打开该代码如下所示:

    if (_cachedSerializerMap != null) {
    synchronized (_cachedSerializerMap) {
    serializer = (Serializer) _cachedSerializerMap.get(cl);
    }
    可以看到此处使用了HashMap,在并发读写map的代码的地方都添加了synchronized 关键字。而本问题也就是在该处BLOCKED了。如果并发较大的时候,线程释放锁的速度赶不上线程争夺资源的速度就会导致用户线程的锁定。

    3.优化方案
    在高并发的场景下,Hashmap+synchronized的锁的粒度太大,直接锁定了整个HashMap对象,那么我们可以用 ConcurrentHashMap来降低锁的粒度,这样并发处理能力就能够增强。

    我在搜索类SerializerFactory的时候,也正好搜索到了hessian-4.0.7.jar中也有这个类,应该是dubbo从hessian里移植过来的另一个类。在这个版本里它就将HashMap替换为ConcurrentHashMap,

    它替换之后的代码是这样的:

    private ConcurrentHashMap _cachedSerializerMap;
    private ConcurrentHashMap _cachedDeserializerMap;

    Serializer serializer;
    if (_cachedSerializerMap != null) {
    serializer = (Serializer) _cachedSerializerMap.get(cl);
    if (serializer != null)
    return serializer;
    }
    它的区别就是使用ConcurrentHashMap ,去除了synchronized 关键字。

    接下来我们也做这样的修改,替换jar包之后,再对服务进行一次压测,结果如下:

    1.线程中无Blocked状态的用户线程。

    2.TPS更加稳定。

    TPS变得更加稳定,没有较大的波动。

    从测试来看这种优化之后是有实际效果的,dubbo服务的并发能力明显增强了许多。



    总结:
    对于并发较高的dubbo服务,若希望提高并发处理能力,则应该做这样的优化。

    摘自:http://www.ithao123.cn/content-8941250.html
    展开全文
  • 因为currenthashmap将数据分段,分成一段一段的,每一段都加锁,锁分离技术,访问的时候,访问第一段数据,第一段加锁,第二段没有锁,其他线程还是可以访问第二段的数据的,所以比自己hashmap加锁的效率要高...

    因为currenthashmap将数据分段,分成一段一段的,每一段都加锁,锁分离技术,访问的时候,访问第一段数据,第一段加锁,第二段没有锁,其他线程还是可以访问第二段的数据的,所以比自己hashmap加锁的效率要高

    展开全文
  • //Exception in thread "Thread-1" Exception in thread "Thread-0" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode // at java.util.HashMap$TreeNode....
    import java.util.ArrayList;
    import java.util.Vector;
    
    /**
     * 并发下的ArrayList
     */
    public class ArrayListMultiThread {
        static ArrayList<Integer> arrayList = new ArrayList<>();
    //    static Vector<Integer> arrayList = new Vector<>(); //解决方式 使用线程安全的Vector代替ArrayList
        public static class AddThread implements Runnable{
            @Override
            public void run() {
    //            synchronized (ArrayListMultiThread.class){  //解决方式加锁
                    for (int i = 0; i < 1000000; i++) {
                        arrayList.add(i);
                    }
    //            }
            }
        }
        public static void main(String[] args) throws InterruptedException{
            Thread thread1 = new Thread(new AddThread());
            Thread thread2 = new Thread(new AddThread());
            thread1.start();
            thread2.start();
            thread1.join();thread2.join();
            System.out.println(arrayList.size());
            //Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: 10
            //  at java.util.ArrayList.add(ArrayList.java:463)
            //  at com.combat.ArrayListMultiThread$AddThread.run(ArrayListMultiThread.java:11)
            //  at java.lang.Thread.run(Thread.java:748)
            //1000001
    
            //这种结果是因为ArrayList在扩容过程中,内部一致性被破坏,但由于没有锁的保护,另一个线程访问到了不一致的内部状态
            //导致出现越界问题
    
            //结果二:2000000
            //结果二:小于2000000
        }
    }
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * 并发下的HashMap
     * jdk8
     */
    public class HashMapMultiThread {
        static Map<String,String> map = new HashMap<>();
    //    static ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>(); //解决方式 用ConcurrentHashMap代替HashMap
        public static class AddThread implements Runnable{
            int start = 0;
            public AddThread(int start){
                this.start = start;
            }
            @Override
            public void run() {
    //            synchronized (HashMapMultiThread.class){ // 解决方式
                    for (int i = start; i < 100000; i+=2) {
                        map.put(Integer.toString(i),Integer.toBinaryString(i));
                    }
    //            }
            }
        }
        public static void main(String[] args) throws InterruptedException{
            Thread thread1 = new Thread(new AddThread(0));
            Thread thread2 = new Thread(new AddThread(1));
            thread1.start();
            thread2.start();
            thread1.join();
            thread2.join();
            System.out.println(map.size());
            //Exception in thread "Thread-1" Exception in thread "Thread-0" java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
            //  at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1832)
            //  at java.util.HashMap$TreeNode.treeify(HashMap.java:1949)
            //  at java.util.HashMap.treeifyBin(HashMap.java:772)
            //  at java.util.HashMap.putVal(HashMap.java:644)
            //  at java.util.HashMap.put(HashMap.java:612)
            //  at com.combat.HashMapMultiThread$AddThread.run(HashMapMultiThread.java:19)
            //  at java.lang.Thread.run(Thread.java:748)
            //java.lang.ClassCastException: java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
            //  at java.util.HashMap$TreeNode.moveRootToFront(HashMap.java:1832)
            //  at java.util.HashMap$TreeNode.putTreeVal(HashMap.java:2012)
            //  at java.util.HashMap.putVal(HashMap.java:638)
            //  at java.util.HashMap.put(HashMap.java:612)
            //  at com.combat.HashMapMultiThread$AddThread.run(HashMapMultiThread.java:19)
            //  at java.lang.Thread.run(Thread.java:748)
            //2778
    
    
            // 结果二:小于100000
    
            //JDk7会出现死循环  HashMap put()是一个迭代遍历,如同遍历链表一样,但由于多线程,链表成环了,形成死循环
        }
    }
    /**
     * Integer加锁
     */
    public class BadLockOnInteger implements Runnable{
        public static Integer i = 0;
        static BadLockOnInteger instance = new BadLockOnInteger();
    
        @Override
        public void run() {
            for (int j = 0; j < 10000000; j++) {
                synchronized (i){
    //            synchronized (instance){ // 修改方式
                    i++; //相当于 i = Integer.valueOf(i.intValue()+1);
                }
            }
        }
        public static void main(String[] args) throws InterruptedException{
            Thread thread1 = new Thread(instance);
            Thread thread2 = new Thread(instance);
            thread1.start();thread2.start();
            thread1.join();thread2.join();
            System.out.println(i);
            //12968375 小于20000000
            //java中Integer属于不变对象,一旦创建就不可能被修改
            //i++的本质是创建一个新的Integer对象,并将他的引用赋值给i
            //两个线程每次加锁可能都加在了不同的对象实例上
        }
    }

    转载于:https://www.cnblogs.com/fly-book/p/11387390.html

    展开全文
  • 加锁方法对于Map

    2016-03-10 16:05:00
    hashmap是不带有锁的,hashtable是带有锁的,多线程使用过程中,需要对hashmap加锁,可以用 1.使用 synchronized 关键字,这也是最原始的方法。代码如下 synchronized(anObject) {  value = map.get(key); } ...

     hashmap是不带有锁的,hashtable是带有锁的,多线程使用过程中,需要对hashmap加锁,可以用

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

    synchronized(anObject)  {   

         value = map.get(key);

    }  

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

    Java代码  复制代码
    1. lock.lock();   
    2. value = map.get(key);   
    3. lock.unlock();  

    3.这样处理时对于hashmap的读写都加锁了,但是如果涉及到少量插入及频繁的查找,那么上面两种的效率不是很高,这时候最好的方式是加读写锁。以下为构造读写锁包装map的方法:

    [java] view plain copy
    1. <span style="font-size:18px;">import java.util.Map;  
    2. import java.util.concurrent.locks.Lock;  
    3. import java.util.concurrent.locks.ReadWriteLock;  
    4. import java.util.concurrent.locks.ReentrantReadWriteLock;  
    5.   
    6. public class ReadWriteMap<K, V> {  
    7.     private final Map<K, V> map;  
    8.     private final ReadWriteLock lock = new ReentrantReadWriteLock();  
    9.     private final Lock r = lock.readLock();  
    10.     private final Lock w = lock.writeLock();  
    11.   
    12.     public ReadWriteMap(Map<K, V> map) {  
    13.         this.map = map;  
    14.     }  
    15.   
    16.     public V put(K key, V value) {  
    17.         w.lock();  
    18.         try {  
    19.             return map.put(key, value);  
    20.         } finally {  
    21.             w.unlock();  
    22.         }  
    23.     }  
    24.   
    25.     public V get(Object key) {  
    26.         r.lock();  
    27.         try {  
    28.             return map.get(key);  
    29.         } finally {  
    30.             r.unlock();  
    31.         }  
    32.     }  
    33. }</span>  

     

     

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

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

    这种方式最快

     

    结论: 

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

     

     

    package com.cyyun.xc.command.util;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import javax.net.ServerSocketFactory;
    
    public class testendpoint {
    
    	protected volatile boolean running = false;
    	/**
    	 * Server socket acceptor thread.
    	 */
    	protected ServerSocket serverSocket = null;
    	protected ServerSocketFactory serverSocketFactory = null;
    
    	public void start() throws Exception {
    		running = true;
    		// 获得serverSocketFactory
    		serverSocketFactory = ServerSocketFactory.getDefault();
    		// 获得serverSocket,监听8080端口
    		serverSocket = serverSocketFactory.createServerSocket(8888);
    		// 建立监听线程
    		Thread acceptorThread = new Thread(new Acceptor(), "-Acceptor-");
    		acceptorThread.start();
    	}
    
    	// 处理socket
    	protected boolean processSocket(Socket socket) throws IOException {
    		BufferedReader in = new BufferedReader(new InputStreamReader(
    				socket.getInputStream()));
    		String inputLine;
    		while ((inputLine = in.readLine()) != null) {
    			System.out.println(inputLine);
    		}
    
    		return true;
    	}
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		testendpoint ts = new testendpoint();
    		try {
    			System.out.println("Server start");
    			ts.start();
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    	}
    
    	// 监听类,不断循环
    	protected class Acceptor implements Runnable {
    
    		/**
    		 * The background thread that listens for incoming TCP/IP connections
    		 * and hands them off to an appropriate processor.
    		 */
    		public void run() {
    
    			// Loop until we receive a shutdown command
    			while (running) {
    
    				// Loop if endpoint is paused
    				// Accept the next incoming connection from the server socket
    				try {
    					Socket socket = serverSocket.accept();
    					// Hand this socket off to an appropriate processor
    					if (!processSocket(socket)) {
    						// Close socket right away
    						try {
    							socket.close();
    						} catch (IOException e) {
    							// Ignore
    						}
    					}
    				} catch (IOException x) {
    
    				} catch (Throwable t) {
    
    				}
    
    				// The processor will recycle itself when it finishes
    
    			}
    
    		}
    
    	}
    }

     

     

    Server start
    GET / HTTP/1.1
    Host: localhost:8888
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    
    POST /aer HTTP/1.1
    Content-Length: 1189
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Host: 127.0.0.1:8888
    Connection: Keep-Alive
    User-Agent: Apache-HttpClient/4.3.5 (java 1.5)
    
    POST / HTTP/1.1
    Content-Length: 1189
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Host: 127.0.0.1:8888
    Connection: Keep-Alive
    User-Agent: Apache-HttpClient/4.3.5 (java 1.5)
    
    POST / HTTP/1.1
    Content-Length: 10
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Host: 127.0.0.1:8888
    Connection: Keep-Alive
    User-Agent: Apache-HttpClient/4.3.5 (java 1.5)
    
    

     

    展开全文
  • 总结:各种加锁方法对于Map

    万次阅读 2012-03-07 15:50:01
    hashmap是不带有锁的,hashtable是带有锁的,多线程使用过程中,需要对hashmap加锁,可以用 1.使用 synchronized 关键字,这也是最原始的方法。代码如下 synchronized(anObject) {  value = map.get(key); }...
  • 对HashMap的理解

    2020-09-26 12:32:34
    1.Map的了解 Map在Java中是一个接口,常见的实现类有HashMap、 LinkedHashMap、TreeMap和ConcurrentHashMap 首先要明确的是,在Java中,哈希表的结构是数组+链表的方式。HashMap底层数据结构是数组+链表/红黑树、...
  • hashmap是不带有锁的,hashtable是带有锁的,多线程使用过程中,需要对hashmap加锁,可以用 1.使用 synchronized 关键字,这也是最原始的方法。代码如下 [code="java"] synchronized(anObject) { ...
  • hashmap是不带有锁的,hashtable是带有锁的,多线程使用过程中,需要对hashmap加锁,可以用 1.使用 synchronized 关键字,这也是最原始的方法。代码如下 synchronized(anObject) {  value = map.get(key); }...
  • Java文件加锁(二)

    千次阅读 2012-12-08 00:35:09
    上一篇文章讲的是文件的加锁,但是在实际的过程中,会产生额外的内存消耗。一个重要的原因是,因为我们是把这些地址和锁存在一个HashMap中的,如果人为不清理的话,这个HashMap里面存放的内容就会越来越多。下面我...
  • 对HashMap的一些浅见

    2020-10-27 22:18:44
    hashmap 在java 1.7 和1.8 有大的区别 1.7 用的是数组 + 链表 1.8及以后 是数组 + 链表 + 红黑树 hashmap数组大小默认是16, hashmap的get,put 操作的时间赋值度是O(1) put的时候,使用 key.hashCode()/16 ...
  • HashMap不是线程安全的。在并发插入元素的时候,有可能... (Hashtable是对hashmap中的方法加上了Synchronize,会锁定整个map)但这两者有着共同的问题:性能。无论读操作还是写操作,它们都会给整个集合加锁,导致...
  • Java8对HashMap和ConcurrentHashMap的改进

    千次阅读 2017-04-05 15:10:27
    1.HashMap 在Java7中,HashMap采用的是数组+链表的形式存储的,(默认bucket数目16,负载因子0.75) 具体见HashMap 那么依照原HashMap,假设bucket=12的数组对应的链表中有10个元素(此时负载仍没超过0.75,10/16)...
  • HashMap

    2020-12-30 10:02:05
    HashMap是一个用于存储Key-Value键值的集合, 每一个键值也叫做Entry. 这些个键值(Entry)分散存储在一个数组当中, 这个数组就是HashMap的主干. HashMap数组每一个元素的初始值都是Null. 对于HashMap, 我们最常...
  • 众所周知,HashMap是线程不安全的。但是如果需要一个线程按钮的HashMap我们需要怎么做的。...public static Map m = Collections.synchronizedMap(new HashMap说白了,就是给HashMap加锁,jdk参考代码如下
  • hashMap

    2021-04-22 08:54:49
    1:HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点。当链表长度超过 8 时,链表转换为红黑树。 transient Node<K,V>[] table; 2:HashMap 的工作原理? HashMap 底层...
  • HashMap(Java8以前):数组+链表 HashMap(Java8及以后):数组+链表+红黑树 如果存入的key是一个自定义的类,该怎么办呢?(重新equals和hashcode) 进入源码: 可以看到key是由Set来存的,就不能够有重复...
  • 集合在客户端加锁

    2011-09-28 23:45:25
    使用线程安全的集合类,我们的操作并不一定是安全...因为客户端的操作并不是原子的,所以通常的办法是在客户端调用时加锁。 例如,Vector,Stack,HashMap等等。 eg: public class UserManager {  private List use
  • HashMap学习

    2019-04-07 21:15:32
    前言   最近在敲Java代码的时候,发现小...     多线操作HashMap,我们通过加锁或者加入同步控制依然能正常应用HashMap,只是需要加上同步操作的代价。 内容   HashMap(键值):基于哈希表实现,使用Hash...
  • 如何全局变量加锁

    万次阅读 2014-06-25 13:57:34
     采用多线程,公用一个全局变量,访问时,如何全局变量加锁? 谢谢! 更多0分享到: 相关主题推荐: 全局变量 多线程 相关帖子推荐: 关于SOCKET多线程编程的问题! 求教大神gcc gnu 下man...
  • HashTable vs HashMap

    2017-08-04 15:57:21
    转载请注明出处:... JDK1.7之 HashMap 源码分析 JDK 1.8之 HashMap 源码分析 HashMap和HashTable有什么区别? HashMap是非线程安全的,HashTable是线程安全的。 HashMap的键和值都
  • HashMap vs HashTable HashMap 的键和值都允许 null...HashMap加锁,所以效率高,非线程安全;HashTable 加锁,是线程安全的,但效率低 ConcurrentHashMap vs HashTable ConcurrentHashMap 是加锁版的 HashMap...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,882
精华内容 16,752
关键字:

对hashmap加锁