线程中的静态同步方法和非静态同步方法

8
"静态同步方法和非静态同步方法不会互相阻塞,它们可以同时运行。"

1
可能是Java中的并发:同步静态方法的重复问题。 - axtavt
3个回答

17
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))。由于它们锁定不同的对象,因此它们不会互相阻塞。

11

在静态方法和非静态方法中,锁对象是不同的。对于静态方法,它使用类对象作为锁(锁对象:MyClass.class),而对于非静态方法,它使用当前方法调用所绑定的实例对象作为锁(锁对象:this)。


我理解了你说的话,但你能否再详细解释一下与该陈述相关的内容,这样对我更清晰明了。 - satheesh
它们可以同时在不同线程中运行,因为锁对象是不同的。通常通过在不同线程中使用相同的锁对象来确保线程安全,在任何时间点上使得这些线程之间代码的执行互斥。 - Chris Dennett
新的 MyClass()?在我看来很令人困惑。锁定 obj:this。 - Vladimir Dyuzhev
是的,你正在锁定这个对象,而不是一个新对象。 - atamanroman
抱歉,我修改了一下。我只是想展示一个实例,但是使用“this”更好 :) - Chris Dennett

0

非静态同步方法在'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();

}

} 在可运行的代码中,先运行一次静态同步方法,然后注释掉静态同步方法并取消注释非静态同步方法调用(同时注释掉静态同步方法),再次运行代码。这样你会更好地理解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接