Java 同步静态方法和非静态方法之间的区别
在java中同步一个静态方法和一个非静态方法有什么区别?有人能用一个例子解释一下吗。同步方法和同步代码块有什么区别吗?简言之,如果在静态方法上同步,则将在类(对象)上同步,而不是在实例(对象)上同步。这意味着在执行静态方法时,整个类都被阻塞。因此,其他静态同步方法也被阻止。Java中的同步基本上是的一种实现。同步非静态方法时,监视器属于实例。在静态方法上同步时,监视器属于该类。同步代码块的想法是相同的,但是监视器属于指定的对象。如果您可以不受影响,那么最好使用同步块,因为它们可以最大限度地减少每个线程在中花费的时间。我将尝试添加一个示例来说明这一点 如前所述,Java中的synchronized是这个概念的一个实现。将代码块标记为已同步时,使用对象作为参数。当执行线程到达这样一个代码块时,它必须首先等待,直到同一对象上的同步块中没有其他执行线程Java 同步静态方法和非静态方法之间的区别,java,synchronization,Java,Synchronization,在java中同步一个静态方法和一个非静态方法有什么区别?有人能用一个例子解释一下吗。同步方法和同步代码块有什么区别吗?简言之,如果在静态方法上同步,则将在类(对象)上同步,而不是在实例(对象)上同步。这意味着在执行静态方法时,整个类都被阻塞。因此,其他静态同步方法也被阻止。Java中的同步基本上是的一种实现。同步非静态方法时,监视器属于实例。在静态方法上同步时,监视器属于该类。同步代码块的想法是相同的,但是监视器属于指定的对象。如果您可以不受影响,那么最好使用同步块,因为它们可以最大限度地减少每
Object a = new Object();
Object b = new Object();
...
synchronized(a){
doStuff();
}
...
synchronized(b){
doSomeStuff();
}
...
synchronized(a){
doOtherStuff();
}
在上面的示例中,运行doOtherStuff()
的线程将阻止另一个线程进入代码块doStuff()
。但是,线程可以毫无问题地进入doSomeStuff()
周围的块,因为该块是在对象b
上同步的,而不是在对象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();
)访问该对象是一样的
因此,在上面的示例中,staticMethodA()
和staticMethodB()
的操作方式相同。执行线程也将被阻止访问nonStaticMethodC()
中的代码块,因为它正在同一对象上同步
Object a = new Object();
Object b = new Object();
...
synchronized(a){
doStuff();
}
...
synchronized(b){
doSomeStuff();
}
...
synchronized(a){
doOtherStuff();
}
但是,重要的是要知道,没有任何东西会阻止正在执行的线程访问
unsastaticmethodd()
。即使我们说静态方法“在类对象上同步”,也并不意味着它同步对该类中方法的所有访问。它只是意味着它使用类对象在上进行同步。非安全访问仍然是可能的。同步块和同步方法之间几乎没有区别。基本上:
void synchronized m() {...}
与
void m() { synchronized(this) {...} }
相比之下,静态同步方法与以下方法相同:
static void m() { synchronized(MyClass.class) {...} }
伙计,只是一个提示。与您的问题无关: 如果有do*Stuff()方法
this.a= /*yet another*/ new Object();
或
那你就完蛋了。因为锁在值内,而不是在引用内。请参见Java线程在进入实例同步Java方法时获取对象级锁,并获取 类级锁,当它进入静态同步java方法时。 通过使用同步块,您只能锁定代码的关键部分,避免锁定可能降低性能的整个方法。来自javadoc 调用静态同步方法时,因为静态方法与类而不是对象相关联。在这种情况下,线程获取与类关联的类对象的内在锁。因此,对类的静态字段的访问由一个锁控制,该锁不同于类的任何实例的锁
public static synchronized void getInstance(){}
当我们获取任何类的锁时,我们实际上获取了“类”类实例的锁,该类实例对于类的所有实例都是唯一的
public synchronized void getInstance(){}
我们可以创建一个类的多个对象,每个对象都有一个与之关联的锁。。。。如果它们也是同步的。只是稍微改进一下:对于静态方法,监视器属于
类
实例,而不是“类”。顺便说一句-如果您必须使用多个类加载器,并且多个类加载器实际加载同一个类,那么这一点非常重要-那么对于同一个类,我们有多个class
实例…@Andreas\D感谢您的澄清。我没有意识到多类加载器之间的细微差别。
public synchronized void getInstance(){}