Java 它是线程安全机制吗?
这个类是线程安全的吗Java 它是线程安全机制吗?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,这个类是线程安全的吗 class Counter { private ConcurrentMap<String, AtomicLong> map = new ConcurrentHashMap<String, AtomicLong>(); public long add(String name) { if (this.map.get(name) == null) { this.map.putIfAbsent(name, new Ato
class Counter {
private ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
if (this.map.get(name) == null) {
this.map.putIfAbsent(name, new AtomicLong());
}
return this.map.get(name).incrementAndGet();
}
}
类计数器{
私有ConcurrentMap=
新的ConcurrentHashMap();
公共长添加(字符串名称){
if(this.map.get(name)==null){
this.map.putIfAbsent(名称,new AtomicLong());
}
返回此.map.get(name).incrementAndGet();
}
}
你觉得怎么样?编辑
如果使地图成为最终地图,则为“是”。否则,不能保证所有线程在第一次调用add()
时都能看到最新版本的map数据结构
几个线程可以到达if()
的主体。putIfAbsent()
将确保仅将单个AtomicLong
放入映射
如果映射中没有新值,putIfAbsent()
将无法返回
因此,当执行第二个get()
时,它将永远不会获得null
值,并且由于只能将单个AtomicLong
添加到映射中,因此所有线程将获得相同的实例
[EDIT2]下一个问题:这有多高效
此代码速度更快,因为它避免了不必要的搜索:
public long add(String name) {
AtomicLong counter = map.get( name );
if( null == counter ) {
map.putIfAbsent( name, new AtomicLong() );
counter = map.get( name ); // Have to get again!!!
}
return counter.incrementAndGet();
}
这就是为什么我更喜欢谷歌的,它有一个在找不到密钥时调用的方法。这样,地图只会被搜索一次,我不必创建额外的实例。是的,前提是您将地图设置为最终地图。if不是必需的,但是如果您愿意,可以出于性能原因保留它,尽管它很可能不会产生明显的差异:
public long add(String name) {
this.map.putIfAbsent(name, new AtomicLong());
return this.map.get(name).incrementAndGet();
}
编辑
为此,我快速测试了这两种实现(有检查和没有检查)。在同一字符串上拨打1000万次电话:
- 250毫秒和支票
- 480毫秒,无需检查
懒散计数器:207毫秒
MPC计数器:303毫秒
最佳计数器:135毫秒
公共类测试{
公共静态void main(字符串args[])引发IOException{
计数器计数=新计数器();
LazyCounter lazyCount=新的LazyCounter();
MPCounter mpCount=新的MPCounter();
BetterCounter betterCount=新的BetterCounter();
//热身
对于(int i=0;i<10_000;i++){
计数。添加(“abc”);
lazyCount.add(“abc”);
mpCount.添加(“abc”);
更好的计算添加(“abc”);
}
//试验
长启动=System.nanoTime();
对于(int i=0;i<10_000;i++){
计数。添加(“abc”);
}
long end=System.nanoTime();
System.out.println((结束-开始)/1000000);
start=System.nanoTime();
对于(int i=0;i<10_000;i++){
lazyCount.add(“abc”);
}
end=System.nanoTime();
System.out.println((结束-开始)/1000000);
start=System.nanoTime();
对于(int i=0;i<10_000;i++){
mpCount.添加(“abc”);
}
end=System.nanoTime();
System.out.println((结束-开始)/1000000);
start=System.nanoTime();
对于(int i=0;i<10_000;i++){
更好的计算添加(“abc”);
}
end=System.nanoTime();
System.out.println((结束-开始)/1000000);
}
静态类计数器{
私有最终ConcurrentMap映射=
新的ConcurrentHashMap();
公共长添加(字符串名称){
this.map.putIfAbsent(名称,new AtomicLong());
返回此.map.get(name).incrementAndGet();
}
}
静态类懒散计数器{
私有最终ConcurrentMap映射=
新的ConcurrentHashMap();
公共长添加(字符串名称){
if(this.map.get(name)==null){
this.map.putIfAbsent(名称,new AtomicLong());
}
返回此.map.get(name).incrementAndGet();
}
}
静态类BetterCounter{
私有最终ConcurrentMap映射=
新的ConcurrentHashMap();
公共长添加(字符串名称){
AtomicLong计数器=this.map.get(名称);
如果(计数器!=null)
返回计数器.incrementAndGet();
AtomicLong newCounter=新的AtomicLong();
计数器=this.map.putIfAbsent(名称,newCounter);
return(counter==null?newCounter.incrementAndGet():counter.incrementAndGet());
}
}
静态类计数器{
私有最终ConcurrentMap映射=
新的ConcurrentHashMap();
公共长添加(字符串名称){
final AtomicLong newVal=新的AtomicLong(),
prevVal=map.putIfAbsent(名称,newVal);
return(prevVal!=null?prevVal:newVal).incrementAndGet();
}
}
}
这个怎么办:
class Counter {
private final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
this.map.putIfAbsent(name, new AtomicLong());
return this.map.get(name).incrementAndGet();
}
}
类计数器{
私有最终ConcurrentMap映射=
新的ConcurrentHashMap();
公共长添加(字符串名称){
this.map.putIfAbsent(名称,new AtomicLong());
返回此.map.get(name).incrementAndGet();
}
}
应该是map
,以确保在调用第一个方法之前,它对所有线程都是完全可见的。(详情请参阅)final
- 我认为
如果
是多余的,我希望我没有监督任何事情
编辑:添加了Java语言规范中的一段引语:我认为您最好使用以下内容:
class Counter {
private ConcurrentMap<String, AtomicLong> map = new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
AtomicLong counter = this.map.get(name);
if (counter == null) {
AtomicLong newCounter = new AtomicLong();
counter = this.map.putIfAbsent(name, newCounter);
if (counter == null) {
// The new counter was added - use it
counter = newCounter;
}
}
return counter.incrementAndGet();
}
}
类计数器{
脉波重复间隔
class Counter {
private ConcurrentMap<String, AtomicLong> map = new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
AtomicLong counter = this.map.get(name);
if (counter == null) {
AtomicLong newCounter = new AtomicLong();
counter = this.map.putIfAbsent(name, newCounter);
if (counter == null) {
// The new counter was added - use it
counter = newCounter;
}
}
return counter.incrementAndGet();
}
}
final AtomicLong newVal = new AtomicLong(),
prevVal = map.putIfAbsent(name, newVal);
return (prevVal != null? prevVal : newVal).incrementAndGet();
public long add(String name) {
AtomicLong counter = this.map.get(name);
if (counter == null) {
AtomicLong newCounter = new AtomicLong();
counter = this.map.putIfAbsent(name, newCounter);
if(counter == null) {
counter = newCounter;
}
}
return counter.incrementAndGet();
}