"静态同步方法和非静态同步方法不会互相阻塞,它们可以同时运行。"
static synchronized void test() { foo(); }
等于
static void test() { synchronized(MyClass.class) { foo(); } }
< p > 当 < /p >synchronized void test() { foo(); }
等于
void test() { synchronized(this) { foo(); } }
这意味着:静态方法锁定在类的类对象上。非静态方法锁定在它们被调用的实例上(默认情况下,也可以使用synchronized(anyOtherLock)
)。由于它们锁定不同的对象,因此它们不会互相阻塞。在静态方法和非静态方法中,锁对象是不同的。对于静态方法,它使用类对象作为锁(锁对象:MyClass.class
),而对于非静态方法,它使用当前方法调用所绑定的实例对象作为锁(锁对象:this
)。
非静态同步方法在'this'上放置监视器锁-这意味着只有当前对象被锁定。因此,如果任何一个线程正在访问非静态同步方法,则与当前对象相关联的所有线程都将被阻止访问该类的非静态同步方法。而其他对象的线程仍然可以访问这些方法。
而静态同步方法则在Class对象上放置监视器锁-这意味着如果任何对象的线程正在访问该方法,则无论任何对象,所有线程都将被阻止访问该类的所有静态同步方法。
public class TestSync {
public synchronized void n1(int threadId)
{
snooze(threadId);
System.out.println("Sync non static n1 " + threadId);
}
public void n2(int threadId)
{
snooze(threadId);
System.out.println(" non static n2 " + threadId);
}
public static synchronized void s1(int threadId)
{
snooze(threadId);
System.out.println("Sync static s1 "+ threadId);
}
public static void s2(int threadId)
{
snooze(threadId);
System.out.println(" static s2 "+ threadId);
}
static void snooze(int threadId)
{
System.out.println("Waiting ... "+ threadId);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TestSync ob = new TestSync();
TestSync ob2=new TestSync();
TestSync ob3=new TestSync();
TestSync ob4=new TestSync();
Runnable r1=()-> {
/*ob.n1(10);
ob.n2(10);*/
ob.s1(10);
//ob.s2(10);
};
Runnable r3=()-> {
/*ob2.n1(30);
ob2.n2(30);*/
ob2.s1(30);
//ob2.s2(30);
};
Runnable r4=()-> {
/*ob3.n1(40);
ob3.n2(40);*/
ob3.s1(30);
//ob3.s2(30);
};
Thread t1=new Thread(r1);
Thread t2= new Thread(r2);
Thread t3= new Thread(r3);
Thread t4= new Thread(r4);
Thread t5= new Thread(r5);
t1.start();
t3.start();
t4.start();
}
} 在可运行的代码中,先运行一次静态同步方法,然后注释掉静态同步方法并取消注释非静态同步方法调用(同时注释掉静态同步方法),再次运行代码。这样你会更好地理解。