0 0

关于ConcurrentHashMap同步的理解?0

在网上看ConcurrentHashMap是线程安全的,我测试的结果却不是这样。

1.开启线程
public class MapRun {
	public static void main(String[] args) {
		
		for(int i = 0 ; i < 10 ; i ++){
			MapKey map = new MapKey();
			new Thread(map).start();
		}

	}
}



public class MapKey implements Runnable {

	
	private final static Map<String , Integer> map = new ConcurrentHashMap<String, Integer>();
	public void run() {
	
		int key = 0;
		if(map.get("taleName") == null){
		  map.put("taleName", 1);
		}
		else{
		    key = map.get("taleName");
			map.put("taleName", key+1);
		}
		System.out.println(map.get("taleName"));
	}
	

}



测试的结果还是有重复的

查了很多资料,这里的线程安全是不是说,ConcurrentHashMap只能存一个相同的变量?
2014年7月09日 14:26

10个答案 按时间排序 按投票排序

0 0

ConcurrentHashMap,put是操作是加了锁的,可以保证是原子操作但是你下面的代码却不是原子操作:

 
        int key = 0;  
        if(map.get("taleName") == null){  
          map.put("taleName", 1);  
        }  
        else{  
            key = map.get("taleName");  
            map.put("taleName", key+1);  
        }  
        System.out.println(map.get("taleName"));  


两个线程同时获取同一个value,假如说是10,这时A线程在执行其他线程在等待,
A线程将值修改为11,这时B线程开始执行,由于获取的值是10,所以这时B线程也会将值设为11,所以造成你所说的重复。
正确写法如下:
synchronized(map) {
   if(map.get("taleName") == null){ 
          map.put("taleName", 1); 
        } 
    ....
}

2014年7月14日 14:01
0 0

源码中get和put均lock(),即确保类是线程安全的。但由线程安全的类组成的新类却不一定是线程安全的,所以需要确定原子操作,对原子操作进行同步,这样才能保证新类是安全的。

2014年7月11日 18:21
0 0

使用putIfAbsent(),不使用

if(map.get("taleName") == null){  
          map.put("taleName", 1);  
        }

完整代码
import java.util.concurrent.ConcurrentHashMap;
public class MapRun {
	public static void main(String[] args) {
		for(int i = 0 ; i < 10 ; i ++){
			MapKey map = new MapKey();
			new Thread(map).start();
		}
	}
}
class MapKey implements Runnable {
	private final static ConcurrentHashMap<String , Integer> map = new ConcurrentHashMap<String, Integer>();

	public void run() {
		map.putIfAbsent("taleName", 0);
		map.put("taleName", map.get("taleName") + 1);
		System.out.println(Thread.currentThread().getName() + "  " + map.get("taleName"));
	}
}


结果:
引用
Thread-0  1
Thread-1  2
Thread-2  3
Thread-3  4
Thread-5  5
Thread-7  6
Thread-9  7
Thread-6  8
Thread-8  9
Thread-4  10

2014年7月11日 11:37
0 0

package org.vocano.java.tst.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MapRun {
	public static void main(String[] args) {
		for(int i = 0 ; i < 10 ; i ++){
			MapKey map = new MapKey();
			new Thread(map).start();
		}
	}
}

class MapKey implements Runnable {
	
	private final static Map<String , Integer> map = new HashMap<String, Integer>();
//	private final static Map<String , Integer> map = new ConcurrentHashMap<String, Integer>();
	
	public void run() {
		int key = 0;
		synchronized (map) {
			if(map.get("taleName") == null){
				map.put("taleName", 1);
			} else {
				key = map.get("taleName");
				map.put("taleName", key+1);
			}
			System.out.println(Thread.currentThread().getName() + "  " + map.get("taleName"));
		}
	}
}


引用
Thread-0  1
Thread-3  2
Thread-2  3
Thread-5  4
Thread-7  5
Thread-4  6
Thread-9  7
Thread-6  8
Thread-8  9
Thread-1  10


题的本意应该是这个,不难理解。

不过这样的话HashMap和ConcurrentHashMap都能实现。

ConcurrentHashMap有什么特别的用处呢?

2014年7月10日 16:38
0 0

线程安全的意思是,一个对象被N个线程同时操都不会坏(对象内部结构乱掉)。
比如HashMap,多个线程同时put时,会死循环的(其内部结构乱掉了)。
ConcurrentHashMap就不会。

2014年7月10日 13:56
0 0

http://www.baike.com/wiki/ConcurrentHashMap

ConcurrentHashMap的get操作是不加锁的,而put是加锁的,这是问题的根源

2014年7月10日 11:06
0 0

ConcurrentHashMap同步,只是指PUT,GET时会有锁,可看源码如put时会有sync.lock()。

这里多个线程跑的时候,MapKey里没有同步。前个线程还没来得及map.put(1),后面就判断map.get()==null了,再一次map.put(1)

2014年7月10日 10:59
0 0

每个线程都创建一个ConcurrentHashMap对象,

2014年7月10日 09:38
0 0

你这个多线程程序创建了多个不同的ConcurrentHashMap对象,都没有同步产生,代码写的不对,应该是多个线程共用一个ConcurrentHashMap对象才对。

2014年7月09日 17:47
0 0

不是ConcurrentHashMap不是线程安全,而是题主对线程安全的理解有问题:

一个类是线程安全的,指的是一次方法调用的范围,而不是多个方法调用。类似于题主的代码,实际上是需要再使用端加上相应的锁才能保证是线程安全的。



synchronized(map) {
   if(map.get("taleName") == null){ 
          map.put("taleName", 1); 
        } 
    ....
}

否则不能保证是线程安全的。

2014年7月09日 15:09

相关推荐

    Java中的ConcurrentHashMap:线程安全的哈希表实现与代码示例

    最后,我们对比了 ConcurrentHashMap 与其他常见并发数据结构的优缺点,帮助读者更好地理解其适用场景和优势。 在实际应用中,我们需要根据具体的场景和需求来选择合适的数据结构。如果需要高并发访问和更新,那么 ...

    java7-8中的 HashMap和ConcurrentHashMap全解析

    因此,如果需要在并发环境中使用,必须使用同步机制,如`synchronized`关键字或`Collections.synchronizedMap()`方法来保证线程安全。 接着,我们来看`ConcurrentHashMap`,它是Java提供的线程安全的散列映射容器,...

    71-ConcurrentHashMap笔记1

    《并发编程:深入理解JDK1.8 ConcurrentHashMap》 ConcurrentHashMap是Java并发编程中不可或缺的一个数据结构,它在JDK1.8中进行了重大的优化,极大地提升了并发性能。相较于早期版本,JDK1.8的ConcurrentHashMap...

    HashMap,HashTable,ConcurrentHashMap之关联.docx

    ConcurrentHashMap 是 Java 中的另一个线程安全的类,它与 HashTable 在线程同步上有什么不同?ConcurrentHashMap 使用了分段锁的机制,每个段都独立锁定,提高了并发性能。 HashMap 和 HashTable 的区别 1. 线程...

    java 同步方法

    【Java 同步方法】是Java编程中...总之,理解和优化Java同步方法的使用,是提高多线程应用程序性能和可伸缩性的核心。通过精细调整同步策略,可以有效地减少争用,提升并发性能,从而让程序在高负载环境下表现更佳。

    Java 多线程与并发(13-26)-JUC集合- ConcurrentHashMap详解.pdf

    关于`HashTable`的慢速,主要原因是它使用`synchronized`关键字对所有操作进行同步,导致在多线程环境下,每次修改整个表都需要获取全局锁,严重影响了并发性能。而`ConcurrentHashMap`通过更细粒度的锁控制和无锁或...

    线成同步异常处理

    2. 使用并发容器:Java提供的ConcurrentHashMap、CopyOnWriteArrayList等并发容器,内部已经实现了线程安全,避免了手动同步。 3. 使用并发工具类:如java.util.concurrent包下的工具类,如ExecutorService、...

    java中的同步和异步的异同共4页.pdf.zip

    总的来说,理解并掌握Java中的同步和异步概念,以及如何在实际编程中合理使用,对于提升Java应用的性能和可维护性具有重要意义。开发者应根据需求权衡同步和异步的优缺点,选择最适合的策略,以实现高效、可靠的并发...

    (Java 综合练习)简单的缓存同步(使用Thread,Timer)

    本实践项目是关于如何使用线程(Thread)和定时器(Timer)来实现一个简单的缓存同步机制。我们将探讨以下几个关键知识点: 1. **线程基础**: - 在Java中,`Thread`类是线程的基类,通过继承或实现`Runnable`接口...

    java_经典Sleep与异步同步并发编程

    - **使用线程安全的集合类**:如 `ConcurrentHashMap`、`CopyOnWriteArrayList` 等。 #### 示例 ```java public class Counter { private int count = 0; public synchronized void increment() { count++; } ...

    java多线程并发及集合框架面试题

    本题旨在考察候选人在实际并发场景下对 HashMap 和 ConcurrentHashMap 的理解和应用。 HashMap 和 ConcurrentHashMap 的主要区别在于它们对并发操作的支持。HashMap 是非线程安全的,意味着在多线程环境中,如果不...

    java同步

    - `java.util.concurrent`包提供了一系列线程安全的容器,如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,它们内部实现了同步机制,以避免外部同步。 7. **volatile关键字** - volatile保证了变量的可见性,...

    深入理解Java内存模型 pdf 超清版

    - Java提供了如`Atomic`系列类、`ConcurrentHashMap`等并发工具,它们基于JMM提供了高效且线程安全的解决方案。 7. **线程安全的实现策略** - 非阻塞同步(如`AtomicInteger`) - 同步块/同步方法(使用`...

    深入学习java并发包ConcurrentHashMap

    在高并发场景下,相比于同步的Collections.synchronizedMap或者使用synchronized关键字修饰的HashMap,ConcurrentHashMap的性能优势更为明显。 总的来说,Java并发包中的ConcurrentHashMap是一个高效且线程安全的散...

    Java线程同步例子.pdf

    在Java中,线程同步是保证多线程安全...上述Java线程同步例子中涉及到的代码虽然是片段,但涵盖了线程同步处理的多个重要方面,帮助我们理解和使用Java线程同步机制,以及在设计和实现多线程应用程序时的实践和技巧。

    java 多线程同步

    包括线程安全集合(如ConcurrentHashMap、CopyOnWriteArrayList等)、线程池(ExecutorService、ThreadPoolExecutor、ScheduledThreadPoolExecutor等)、信号(CountDownLatch、CyclicBarrier、Semaphore等)以及...

    java Thread & synchronized & concurrent 线程、同步、并发

    总之,理解和掌握Java中的线程、同步和并发是构建高效、可扩展的多线程应用程序的关键。合理地使用这些工具和机制,可以帮助我们编写出更加健壮、高效的代码。在实际开发中,根据具体需求选择合适的方法,平衡性能和...

    java同步与互斥资料收集

    最后,理解并发集合类(如`ConcurrentHashMap`、`CopyOnWriteArrayList`等)的工作原理也很重要。这些集合类内部已经实现了线程安全,可以避免在并发环境下使用普通集合引发的问题。 在分析这个资料集时,你可能会...

    LRUCache实现 同步LRUCache

    2. 使用`ConcurrentHashMap`:虽然`LinkedHashMap`本身不是线程安全的,但我们可以使用`ConcurrentHashMap`来存储内部节点,这样可以避免锁竞争,提高并发性能。 线程安全的LRUCache实现会相对复杂,涉及到`...

Global site tag (gtag.js) - Google Analytics