4

我有两个线程可以访问一个对象。使用同步(a),我在对象a上提供锁,所以现在每次线程都可以访问对象“a”并修改它。如果执行此代码,我们有1 2。有时没有同步块我们得到2 2。(线程 t1 得到 i 并增加 i 现在线程 t2 得到 i 并增加然后线程 t1 得到 i 并打印 2,线程 t2 也得到 i 并打印 2)如果我是真的为什么我们不能使用同步(这个)而不是同步(一个)?

public class Foo {

    public static void main(String[] args) {
        B b =new B();
        b.start();

    }

}
class B{

    A a = new A();
    Thread t1 =new Thread(new Runnable(){
        public void run(){
            synchronized(a){

                a.increment();

            }
        }
    });
    Thread t2 =new Thread(new Runnable(){
        public void run(){
            synchronized(a){

                a.increment();

            }
        }
    });
    public void start(){
        t1.start();
        t2.start();
    }

}
class A{
    int i = 0;
    public void increment() {
        i++;
        System.out.println(i);
    }
}
4

2 回答 2

4

如果我是真的,为什么我们不能使用同步(this)而不是同步(a)?

如果你这样做了:

public void run() {
    synchronized (this) {
        a.increment();
    }
}

this这种情况下是封闭类实例,这里是一个匿名 Runnable 对象,并且由于每个线程都有自己的 Runnable 实例,因此您的同步是在单独的对象上进行的,并且不会起作用。您必须进行同步B.this才能使其正常工作。

public void run() {
    synchronized (B.this) {
        a.increment();
    }
}

或任何其他对所有同步块都相同的唯一对象。

或者,如果您想使用synchronized (this),则使用单个 Runnable:

class B {
    A a = new A();

    Runnable r = new Runnable() {
        public void run() {
            synchronized (this) {
                a.increment();
            }
        };
    };

    public void start() {
        // t1.start();
        // t2.start();

        new Thread(r).start();
        new Thread(r).start();
    }
}
于 2018-09-02T13:48:29.770 回答
3

另一种方法:

使方法increment同步

public class Foo {

    public static void main(String[] args) {
        new B().start();
    }
}

class B {

    A       a   = new A();
    Thread  t1  = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        a.increment();
                    }
                });
    Thread  t2  = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        a.increment();
                    }
                });

    public void start() {
        t1.start();
        t2.start();
    }
}

class A {

    int i = 0;

    public synchronized void increment() {   // <<<<<<<<
        i++;
        System.out.println(i);
    }
}
于 2018-09-02T13:48:01.600 回答