-1

线程t1正在调用test1()Test类对象ob的方法。
线程在同步块t2中调用test1()Test类对象ob的方法。即使ob 的方法调用在线程的同步块中,
t1也能够调用ob 的方法。test1()test1()t2

代码如下:

class Test {
    void test1() {
        while(1 == 1) {
            System.out.println(Thread.currentThread().getName() + " test1!");
        }
    }

    void test2() {
        while(1 == 1) {
            System.out.println(Thread.currentThread().getName() + " test2!");
        }
    }
}

class NewThread1 implements Runnable {
    Thread t;
    String name;
    Test target;

    NewThread1(Test ob, String threadname) {
        target = ob;
        name = threadname;
        t = new Thread(this, name);
    }

    public void run() {
        target.test1();
    }
}

class NewThread2 implements Runnable {
    Thread t;
    String name;
    Test target;

    NewThread2(Test ob, String threadname) {
        target = ob;
        name = threadname;
        t = new Thread(this, name);
    }

    public void run() {
        synchronized(target) {
            target.test1();
        }
    }
}

class Test1 {
    public static void main(String args[]) {
        Test ob = new Test();
        NewThread1 t1 = new NewThread1(ob, "t1");
        NewThread2 t2 = new NewThread2(ob, "t2");

        t2.t.start();
        t1.t.start();

        try {
            t1.t.join();
            t2.t.join();
        } catch(InterruptedException e) {
            System.out.println("Main thread interrupted");
        }

        System.out.println("Main thread exiting");
    }
}
4

1 回答 1

0

由于NewThread1#run()未同步,它不会尝试获取目标上的监视器,因此不会被阻塞,即使另一个线程拥有它的监视器,它也可以调用目标上的方法。

Synchronized如果所有线程都与具有同步部分的同一监视器竞争,则只能独占锁定其他线程。(您调用 test1 或 test2 都没有关系,检查发生在基于目标的同步中)。您可以做的是使 test1 和 test2 同步方法,然后他们将尝试在所有情况下保留实例的监视器)。这不仅适用于独占执行,而且适用于您可能希望退出同步块的任何内存访问保证(发生在之后)。

顺便说一句,你不需要不同的线程类,如果你只使用一个(同步的那个)它会像预期的那样工作。

Thread t1 = new NewThread2(ob, "t1");
Thread t2 = new NewThread2(ob, "t2");

但是,如果您的锁定范围很窄,最好在 target 的(所有)实例方法中本地化锁定Test,因为这样您就永远无法在缺少同步的情况下调用它们(并且您可以在没有调用者的情况下切换到其他锁定原语必须知道)。

void synchronized test1() {
    while(1 == 1) {
        System.out.println(Thread.currentThread().getName() + " test1!");
    }
}

或者

void test1() {
    synchronized(this) {
        while(1 == 1) {
            System.out.println(Thread.currentThread().getName() + " test1!");
        }
    }
}
于 2019-01-26T20:20:13.970 回答