同步静态方法和非静态方法之间的区别

在java中同步静态方法和非静态方法有什么区别?任何人都可以用一个例子来解释。 同步方法和同步代码块有什么区别吗?

我将尝试添加一个示例以使此更加清晰。

如前所述,Java中的synchronized是Monitor概念的一种实现。 将代码块标记为已同步时,请使用对象作为参数。 当执行线程进入这样的代码块时,它必须首先等待,直到该同一对象上的同步块中没有其他正在执行的线程。

Object a = new Object(); Object b = new Object(); ... synchronized(a){ doStuff(); } ... synchronized(b){ doSomeStuff(); } ... synchronized(a){ doOtherStuff(); } 

在上面的例子中,运行doOtherStuff()的线程会阻止另一个线程进入保护doStuff()的代码块。 但是一个线程可以在没有问题的情况下进入doSomeStuff()周围的块,因为它在Object b上同步,而不是Object a。

在实例方法(非静态方法)上使用synchronized修饰符时,它与具有“this”作为参数的synchronized块非常相似。 因此在下面的示例中,methodA()和methodB()的行为方式相同:

 public synchronized void methodA() { doStuff(); } ... public void methodB() { synchronized(this) { doStuff(); } } 

请注意,如果该类中的methodC()未同步且没有同步块,则不会阻止线程进入该方法,粗心的编程可能会让该线程访问该对象中的非安全代码。

如果你有一个带有synchronized修饰符的静态方法,它实际上与使用ClassName.class作为参数的同步块是一样的(如果你有该类的对象, ClassName cn = new ClassName();你可以使用Class c = cn.getClass(); )访问该对象

 class ClassName { public void static synchronized staticMethodA() { doStaticStuff(); } public static void staticMethodB() { synchronized(ClassName.class) { doStaticStuff(); } } public void nonStaticMethodC() { synchronized(this.getClass()) { doStuff(); } } public static void unSafeStaticMethodD() { doStaticStuff(); } } 

所以在上面的例子中,staticMethodA()和staticMethodB()的行为方式相同。 执行线程也将被阻止访问nonStaticMethodC()中的代码块,因为它正在同一对象上进行同步。

但是,重要的是要知道没有什么能阻止正在执行的线程访问unSafeStaticMethodD()。 即使我们说静态方法“在Class对象上同步”,也不意味着它同步对该类中方法的所有访问。 它只是意味着它使用Class对象进行同步。 仍然可以进行非安全访问。

简而言之,如果您在静态方法上进行同步,则将在类(对象)上进行同步,而不是在实例(对象)上进行同步。 这意味着在执行静态方法时,整个类都被阻止。 因此其他静态同步方法也被阻止。

Java中的同步基本上是监视器的实现。 同步非静态方法时,监视器属于实例。 在静态方法上同步时,监视器属于该类。 同步代码块是一样的想法,但监视器属于指定的对象。 如果你可以逃脱它,最好使用synchronized块,因为它们可以减少每个线程在关键部分花费的时间

同步块和同步方法之间几乎没有区别。 基本上:

 void synchronized m() {...} 

是相同的

 void m() { synchronized(this) {...} } 

相比之下,静态同步方法与以下内容相同:

 static void m() { synchronized(MyClass.class) {...} } 

伙计,只是一个暗示。 与您的问题无关:

如果有任何do * Stuff()方法也可以

 this.a= /*yet another*/ new Object(); 

要么

 this.b= /*yet another*/ new Object(); 

然后你被搞砸了。 因为锁在值内,而不在引用内。 请参阅Java同步引用

Java Thread在进入实例synchronized java方法时获取对象级锁,并在进入静态同步java方法时获取类级锁。 通过使用synchronized块,您只能锁定代码的关键部分,并避免锁定可能降低性能的整个方法。

来自javadoc https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

当调用静态同步方法时,因为静态方法与类关联,而不是与对象关联。 在这种情况下,线程获取与类关联的Class对象的内部锁。 因此,对类的静态字段的访问由一个锁控制,该锁与该类的任何实例的锁不同。

 public static synchronized void getInstance(){} 

当我们获取任何类的锁时,我们实际上获得了对“Class”类实例的锁定,该实例只对所有类的实例都有一个。

 public synchronized void getInstance(){} 

我们可以创建一个类的多个对象,每个对象都有一个与之关联的锁。