AtomicReference和Synchronized之间有什么区别吗?
例如.
例如.
public class Internet { AtomicReference<String> address; public String getAddress(){ return address.toString(); } public void setAddress(String address) { this.address.set(address); } }
我将类传递给一些尝试同时使用该类的线程,如果我使用它是同样的事情:
public class Internet { String address; public String getAddress(){ return address; } public void setAddress(String address) { this.address = address; } }
然后在线程使用synchronized之前访问类?
解决方法
您没有在第一个示例中初始化引用,它可能应该是:
public class Internet { AtomicReference<String> address = new AtomicReference<String>(); public String getAddress(){ String s = address.get(); return s == null ? null : s.toString(); } public void setAddress(String address) { this.address.set(address); } }
访问限制所在的位置很重要.如果你把控件放在被访问的对象中,那么它可以单独控制它的不变量,这比依赖线程正确地进行所有同步要脆弱得多,其中一个行为不当的访问线程可能破坏被访问的东西.所以第一个例子在该帐户上要好得多.
如果您更改第二个示例,以便对象可以控制自己的锁定(因此它不依赖于访问它的线程来安全地执行此操作),如下所示:
public class Internet { private final Object lock = new Object(); private String s; public String getAddress() { synchronized(lock) { return s; } } public void setAddress(String s) { synchronized(lock) { this.s = s; } } }
然后它是一个更接近的比较,一个依赖于锁定而另一个依赖于原子引用.使用AtomicReference的那个尝试使用机器级原子处理指令来避免锁定.哪个更快可能取决于您的硬件和jvm以及处理负载,通常原子方法应该更快.同步方法是一种更通用的机制;使用synchronized块,您可以更轻松地将多个分配组合在一起,其中使用原子引用更加复杂.
As James says in his answer,同步您的线程正在等待锁定;没有超时,死锁是可能的.使用原子引用,线程进行更改而不等待共享锁.
实现这一目标的最简单且性能最佳的方法是组织代码,以便可以使对象不可变,这样就可以避免所有锁定,忙等待和缓存更新:
public final class Internet { private final String s; public Internet(String s) { this.s = s; } public String getAddress() {return s;} }
按优先顺序降序排列:
>尽可能选择不变性.>对于不可变的代码,尝试将变异限制在一个线程中.>如果只需要在线程之间进行一项更改,请使用原子方法.>如果跨线程的多个更改需要在不受其他线程干扰的情况下发生,请使用锁定.