我试图确保我了解Java中同步的性能含义。我有几个简单的类:
public class ClassOne {
private ClassTwo classTwo = new ClassTwo();
public synchronized void setClassTwo(int val1, int val2) {
classTwo.setVal(val1);
classTwo.setVal2(val2);
}
public static void main(String[] args) {
ClassOne classOne = new ClassOne();
classOne.setClassTwo(10, 100);
}
}
public class ClassTwo {
private int val;
private int val2;
public synchronized void setVal(int val) {
this.val = val;
}
public synchronized void setVal2(int val2) {
this.val2 = val2;
}
}
因此,如您在前面的示例中看到的,我正在ClassOne.setClassTwo和ClassTwo.setVal和ClassTwo.setVal2上进行同步。我想知道的是,如果删除ClassTwo.setVal和ClassTwo.setVal2上的同步,性能是否完全相同,如下所示:
public class ClassTwo {
private int val;
private int val2;
public void setVal(int val) {
this.val = val;
}
public void setVal2(int val2) {
this.val2 = val2;
}
}
在这种情况下,它们在功能上是等效的(假设没有其他类在使用这些类),但是想知道进行更多同步会带来多少开销(如果有)。
会有开销吗?是。
会有很多开销吗?依靠。
如果只有一个线程,那么答案是“否”,即使在古代,无人参与的同步也很快,据推测,自那时以来,同步甚至变得更好。
那么,如果线程数多于1怎么办?问题就在这里:您发布的2个版本在功能上并不等效。为什么?因为您要调用的子方法是公共类的公共方法。因此,可以在您的外部调用它们setClassTwo
,因此-没有同步。
要注意的另一件事是它们在不同的监视器上同步。第二个版本仅在1个监视器上同步,而第二个版本在2个监视器上同步。
TL; DR
保留synchronized
需要同步的方法,不要仅仅期望调用者进行同步(除非它嵌入在类API中)。如果调用方法正确地执行了同步,则将不会有争用,开销将非常小,如果它们以某种方式无法做到(例如,通过直接调用您的方法的人),那么您将获得争用和更大的开销-但是您仍然具有线程安全性。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句