在Java中将此关键字与同步块一起使用

时间:2018-09-02 13:10:58

标签: java multithreading synchronized-block

我有两个可以访问对象的线程。使用synced(a),我在对象a上提供了锁定,因此现在每次线程上的线程都可以访问对象“ a”并对其进行修改。如果执行此代码,我们将得到1 2.在没有同步块的情况下,有时会得到2 2。(线程t1获取i并增加i现在线程t2获取i并递增,然后线程t1获得i并打印2,线程t2获取i并打印2) 如果我是对的,为什么我们不能使用synced(this)而不是synceded(a)?

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);
    }
}

2 个答案:

答案 0 :(得分:4)

  

如果我是真的,为什么我们不能使用synced(this)而不是synceded(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();
    }
}

答案 1 :(得分:1)

另一种方法:

使方法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);
    }
}