我将尝试添加示例以使这一点更加清楚。
如前所述,Java中的同步是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。
在实例方法(非静态方法)上使用synced修饰符时,它与使用“
this”作为参数的同步块非常相似。因此,在以下示例中,
methodA()和
methodB()将以相同的方式起作用:
public synchronized void methodA() { doStuff();}...public void methodB() { synchronized(this) { doStuff(); }}请注意,如果
methodC()该类中有一个不同步且没有同步块的类,则什么也不会阻止线程进入该方法,并且粗心的编程可能会使该线程访问对象中的非安全代码。
如果您有一个带有synced修饰符的静态方法,则实际上与使用synced块
ClassName.class作为参数是一样的(如果您拥有该类的对象
ClassNamecn = 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对象进行同步。仍然可以进行非安全访问。



