4

I have two thread that have access to an object. with synchronized(a), i supply lock on object a so now in each time on thread can access to object "a" and modify that.if execute this code we have 1 2. without synchronized block some times we get 2 2 .(thread t1 get i and increment i now thread t2 get i and increment that then thread t1 get i and print 2 ,also thread t2 get i and print 2) if i am true why we can not use synchronized(this) instead of synchronized(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);
    }
}
kankan256
  • 210
  • 1
  • 4
  • 18

2 Answers2

4

if i am true why we can not use synchronized(this) instead of synchronized(a)?

If you did:

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

The this in this case is the enclosing class instance, here an anonymous Runnable object, and since each thread has its own Runnable instance, then your synchronization is on separate objects, and won't work. You would have to synchronize on B.this for it to work.

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

or any other unique object that is the same for all synchronization blocks.

Or if you wanted to use synchronized (this), then use a single 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();
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
3

Another approach:

Make method increment synchronized

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);
    }
}
Stéphane Millien
  • 3,238
  • 22
  • 36