Java赋值问题 - 这是原子的吗? [英] Java assignment issues - Is this atomic?

查看:188
本文介绍了Java赋值问题 - 这是原子的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Java的分配有一些疑问。

I've got some questions about Java's assigment.


  • 字符串

我有一个课程:

public class Test {
 private String s;

 public synchronized void setS(String str){
  s = s + " - " + str;
 }

 public String getS(){
  return s;
 }
}

我在我的setter中使用synchronized,并且在我的getter中避免它,因为在我的应用程序中,有大量数据获取,并且设置很少。必须同步设置以避免不一致。我的问题是:获取和设置变量原子?我的意思是,在多线程环境中,Thread1即将设置变量s,而Thread2即将获得s。有没有办法getter方法可以得到一些不同于s的旧值或s的新值(假设我们只有两个线程)?
在我的应用程序中获取新值不是问题,获取旧值不是问题。但是我可以得到别的东西吗?

I'm using "synchronized" in my setter, and avoiding it in my getter, because in my app, there are a tons of data gettings, and very few settings. Settings must be synchronized to avoid inconsistency. My question is: is getting and setting a variable atomic? I mean, in a multithreaded environment, Thread1 is about to set variable s, while Thread2 is about to get "s". Is there any way the getter method could get something different than the s's old value or the s's new value (suppose we've got only two threads)? In my app it is not a problem to get the new value, and it is not a problem to get the old one. But could I get something else?


  • HashMap的获取和推送怎么样?

考虑到这一点:

    public class Test {
        private Map<Integer, String> map = Collections.synchronizedMap(new HashMap<Integer, String>());

        public synchronized void setMapElement(Integer key, String value){
         map.put(key, value);
        }

        public String getValue(Integer key){
         return map.get(key);
        }
}

放入和获取原子? HashMap如何处理将元素放入其中?它首先删除旧值并放入现在的值吗?我可以获得除旧值或新值以外的其他值吗?

Is putting and getting atomic? How does HashMap handle putting an element into it? Does it first remove the old value and put the now one? Could I get other than the old value or the new value?

提前致谢!

推荐答案

在第一种情况下, String 对于不安全的发布(在新的Java内存模型(JMM)中)是安全的,所以这是好吧。

In the first case, String happens to be safe for unsafe publication (in the "new" Java Memory Model (JMM)), so this is okay.

不是 volatile 理论上存在一些问题,即没有最新值,但是最新的含义尚不清楚。您可以使用compare-sand-swap(CAS)循环替换锁定,但是无论锁定是否有争议,这可能不会给您带来太多的性能提升。

Not being volatile there is theoretically some issue with not having an up to date value, but then the meaning of up to date is not clear. You could replace the lock with a compare-sand-swap (CAS) loop, but that probably wouldn't give you much performance gain whether the lock was likely to be contended or not.

HashMap 的情况下,如果有另一个线程写入它,即使是单个编写器线程,也不能安全地读取未同步的映射。实际上,已发现这会导致运行流行软件的生产系统出现无限循环。问题中的代码实际上对映射使用了两个锁,它位于顶部(尽管如果使用迭代器,您需要显式保持相同的锁)。不是 final 会阻止包含类对于不安全的发布是安全的。如果 map volatile ,你为每个 put ,那么可以在没有同步的情况下使其安全。

In the case of HashMap, an unsynchronized map is not safe to read if there is another thread writing to it, even a single writer thread. In fact, this has been found to lead to infinite loops on production systems running popular software. The code in the question actually uses two locks for the map, which is over the top (although you'd need an explicit hold of the same lock if using an iterator). Not being final does stop the containing class from being safe for unsafe publication. If map was volatile and you created a new map for every put, then that could be made to be safe without synchronisation on the get.

这篇关于Java赋值问题 - 这是原子的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆