используя это ключевое слово с синхронизированным блоком в Java - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть два потока, которые имеют доступ к объекту. с помощью synchronized (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);
    }
}

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

если я прав, почему мы не можем использовать синхронизированный (это) вместо синхронизированного (а)?

Если вы сделали:

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();
    }
}
0 голосов
/ 02 сентября 2018

Другой подход:

Сделать метод 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);
    }
}
...