Java 同步静态方法和非静态方法的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6367885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
difference between synchronizing a static method and a non static method
提问by Ammu
What is the difference between synchronizing a static method and a non static method in java?Can anybody please explain with an example. Also is there any difference in synchronizing a method and synchronizing a block of code?
java中同步静态方法和非静态方法有什么区别? 谁能举个例子解释一下。同步方法和同步代码块有什么区别吗?
采纳答案by Daniel Lundmark
I will try and add an example to make this extra clear.
我将尝试添加一个示例来使这一点更加清晰。
As has been mentioned, synchronized in Java is an implementation of the Monitorconcept. When you mark a block of code as synchronized you use an object as a parameter. When an executing thread comes to such a block of code, it has to first wait until there is no other executing thread in a synchronized block on that same object.
如前所述,Java 中的同步是监视器概念的实现。当您将代码块标记为同步时,您使用一个对象作为参数。当一个正在执行的线程遇到这样的代码块时,它必须首先等待,直到同一个对象的同步块中没有其他正在执行的线程。
Object a = new Object();
Object b = new Object();
...
synchronized(a){
doStuff();
}
...
synchronized(b){
doSomeStuff();
}
...
synchronized(a){
doOtherStuff();
}
In the above example, a thread running doOtherStuff()
would block another thread from entering the block of code protecting doStuff()
. However, a thread could enter the block around doSomeStuff()
without a problem as that is synchronized on Object b
, not Object a
.
在上面的例子中,一个正在运行的线程doOtherStuff()
会阻止另一个线程进入保护代码块doStuff()
。但是,线程可以doSomeStuff()
毫无问题地进入该块,因为它是在 上同步的Object b
,而不是在 上Object a
。
When you use the synchronized modifier on an instance method (a non-static method), it is very similar to having a synchronized block with "this" as the argument. So in the following example, methodA()
and methodB()
will act the same way:
当您在实例方法(非静态方法)上使用 synchronized 修饰符时,它与使用“this”作为参数的同步块非常相似。因此,在下面的例子中,methodA()
并methodB()
会采取同样的方式:
public synchronized void methodA() {
doStuff();
}
...
public void methodB() {
synchronized(this) {
doStuff();
}
}
Note that if you have a methodC()
in that class which is not synchronized and does not have a synchronized block, nothing will stop a thread from entering that method and careless programming could let that thread access non-safe code in the object.
请注意,如果methodC()
该类中有一个未同步且没有同步块的 ,则没有什么可以阻止线程进入该方法,并且粗心的编程可能会让该线程访问对象中的非安全代码。
If you have a static method with the synchronized modifier, it is practically the same thing as having a synchronized block with ClassName.class
as the argument (if you have an object of that class, ClassName cn = new ClassName();
, you can access that object with Class c = cn.getClass();
)
如果您有一个带有 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();
}
}
So in the above example, staticMethodA()
and staticMethodB()
act the same way. An executing thread will also be blocked from accessing the code block in nonStaticMethodC()
as it is synchronizing on the same object.
所以在上面的例子中,staticMethodA()
并staticMethodB()
采取同样的方式。一个正在执行的线程也将被阻止访问代码块,nonStaticMethodC()
因为它在同一个对象上同步。
However, it is important to know that nothing will stop an executing thread from accessing unSafeStaticMethodD()
. Even if we say that a static method "synchronizes on the Class object", it does not mean that it synchronizes all accesses to methods in that class. It simply means that it uses the Class object to synchronize on. Non-safe access is still possible.
但是,重要的是要知道没有什么可以阻止正在执行的线程访问unSafeStaticMethodD()
. 即使我们说静态方法“在 Class 对象上同步”,也不意味着它同步了对该类中方法的所有访问。它只是意味着它使用 Class 对象进行同步。非安全访问仍然是可能的。
回答by PeterMmm
In short if you synchronize on a static method you will synchronize on the class (object) and not on an instance (object). That means while execution of a static method the whole class is blocked. So other static synchronized methods are also blocked.
简而言之,如果您在静态方法上同步,您将在类(对象)而不是实例(对象)上进行同步。这意味着在执行静态方法时,整个类都会被阻止。所以其他静态同步方法也被阻塞了。
回答by jpm
Synchronization in Java is basically an implementation of monitors. When synchronizing a non static method, the monitor belongs to the instance. When synchronizing on a static method, the monitor belongs to the class. Synchronizing a block of code is the same idea, but the monitor belongs to the specified object. If you can get away with it, synchronized blocks are preferable because they minimize the time each thread spends in the critical section
Java 中的同步基本上是监视器的实现。同步非静态方法时,监视器属于实例。在静态方法上同步时,监视器属于该类。同步一个代码块是同样的想法,但监视器属于指定的对象。如果你能摆脱它,同步块是可取的,因为它们最大限度地减少了每个线程在临界区花费的时间
回答by Nick
There is virtually no difference between synchronizing a block and synchronizing a method. Basically:
同步块和同步方法之间几乎没有区别。基本上:
void synchronized m() {...}
is the same as
是相同的
void m() { synchronized(this) {...} }
By comparison a static synchronized method is the same as:
相比之下,静态同步方法与以下内容相同:
static void m() { synchronized(MyClass.class) {...} }
回答by PyMeH
Dude, just a hint. Not related to your question:
哥们,给个提示。与您的问题无关:
If any do*Stuff() methods does either
如果有任何 do*Stuff() 方法
this.a= /*yet another*/ new Object();
or
或者
this.b= /*yet another*/ new Object();
then you are screwed. Because the lock is inside the value, not inside the reference. See Java synchronized references
那你就完蛋了。因为锁在值内部,而不是在引用内部。请参阅Java 同步参考
回答by Zia
Java Thread acquires an object level lock when it enters into an instance synchronized java methodand acquires a class level lock when it enters into static synchronized java method. By using synchronized blockyou can only lock critical section of code and avoid locking whole method which can possibly degrade performance.
Java线程在进入实例同步java方法时获取对象级锁,进入静态同步java方法时获取类级锁。通过使用同步块,您只能锁定代码的关键部分并避免锁定可能会降低性能的整个方法。
回答by Saurabh
From javadoc https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
来自 javadoc https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
当调用静态同步方法时,因为静态方法与类相关联,而不是与对象相关联。在这种情况下,线程获取与类关联的 Class 对象的内在锁。因此,对类的静态字段的访问由与类的任何实例的锁不同的锁控制。
public static synchronized void getInstance(){}
When we acquire a lock on any class, we actually acquire a lock on "Class" class instance which is only one for all instances of class.
当我们获取任何类的锁时,我们实际上获取了对“Class”类实例的锁,该锁对于类的所有实例都是一个。
public synchronized void getInstance(){}
we can create multiple object's of a class and each object will have one lock associated with it.
我们可以创建一个类的多个对象,每个对象都有一个与之关联的锁。