Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using this keyword with synchronized block in java

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);
    }
}
like image 958
kankan256 Avatar asked Mar 05 '23 12:03

kankan256


2 Answers

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();
    }
}
like image 148
Hovercraft Full Of Eels Avatar answered Apr 12 '23 22:04

Hovercraft Full Of Eels


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);
    }
}
like image 43
Stéphane Millien Avatar answered Apr 12 '23 22:04

Stéphane Millien