1

Driver.java

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Driver {

    static Lock lock = new ReentrantLock();
    static Integer incr = 20;

    public static void main(String [] arg) throws InterruptedException
    {
        Thread thr1 = new Thread(new Runnable(){
            @Override
            public void run() {
                lock.lock();
                System.out.println("Gained access! - 1");
                try {Thread.sleep(5000);} catch (InterruptedException e) {}
                incr++;
                lock.unlock();
            }
        });

        Thread thr2 = new Thread(new Runnable(){
            @Override
            public void run() {
                lock.lock();
                System.out.println("Gained access! - 2");
                incr++;
                lock.unlock();
            }
        });

        Thread thr3 = new Thread(new Runnable(){
            @Override
            public void run() {
                synchronized(incr){                 
                    System.out.println("Gained access! - 3");
                    try {Thread.sleep(5000);} catch (InterruptedException e) {}
                    incr++;
                }
            }
        });

        Thread thr4 = new Thread(new Runnable(){
            @Override
            public void run() {
                synchronized(incr){
                    System.out.println("Gained access! - 4");
                    incr++;
                }
            }
        });

        thr1.start();
        thr2.start();
        thr3.start();
        thr4.start();

        thr1.join();
        thr2.join();
        thr3.join();
        thr4.join();

        System.out.println(incr);
    }
}

Run 1 - Output

Gained access! - 3
Gained access! - 2
Gained access! - 1
Gained access! - 4
23

Run 2 - Output

Gained access! - 1
Gained access! - 4
Gained access! - 3
Gained access! - 2
24

Run N - Output

Switching orders of Thread execution. Seen it hit a sum of 22.

Questions

I am attempting to do a simple Reentrant lock and syncrhonized practice.

  1. Do these outputs indicate that ReentrantLock is using synchronized internally?
  2. Are these locks/synchronized basically while loops until a variable is accessible or is execution actually paused (in bytecode) until Objects/Locks are unlocked?
  3. Why isn't the sum always 24 in case above? The threads do the following:

    Thread 1: Lock| 5s wait | value++
    Thread 2: Lock| 0s wait | value++
    Thread 3: syncronized | 5s wait | value++
    Thread 4: syncronized | 0s wait | value++

4. Can someone confirm if this basically what synchronized is doing internally? My knowledge of the internal workings of synchronized is minimal. This is something I thought might be a logical way to replicate synchronized. So, again I am not sure if this is the right way. So please let me know if the internal workings in Java are different from this.

public class Driver {

    static Safe<Integer> value = new Safe<Integer>(20);

    public static void main(String [] arg) throws InterruptedException
    {
        Thread thr1 = new Thread(new Runnable(){
            @Override
            public void run() {             
                value.lock();
                System.out.println("Gained access! - 1");
                value.data++;
                try {Thread.sleep(5000);} catch (InterruptedException e) {}
                value.unlock();
            }
        });

        Thread thr2 = new Thread(new Runnable(){
            @Override
            public void run() {
                value.lock();
                System.out.println("Gained access! - 2");
                value.data++;
                try {Thread.sleep(5000);} catch (InterruptedException e) {}
                value.unlock();
            }
        });


        thr1.start();
        thr2.start();

        thr1.join();
        thr2.join();

        System.out.println(value);
    }
}

class Safe<E>{
    private volatile boolean lock = false;
    protected E data;

    public Safe(E d)
    {
        data = d;
    }
    public String toString()
    {
        return data.toString();
    }
    public void lock()
    {
        while(isLocked()){}
        lock = true;
    }
    public void unlock()
    {
        lock = false;
    }
    public boolean isLocked()
    {
        return lock;
    }
}

Thank you!

That1Guy
  • 7,075
  • 4
  • 47
  • 59
Mathew Kurian
  • 5,949
  • 5
  • 46
  • 73
  • Your Safe class is inaptly named, since it's quite unsafe. It doesn't synchronize access to it's internals, and it uses a spin lock (which is almost guaranteed to hang the system). – Hot Licks Dec 03 '13 at 01:30
  • @HotLicks Go easy lol. Im still a newbie. Can you explain how so? – Mathew Kurian Dec 03 '13 at 01:31
  • Well, you gotta lock the lock. And sitting in a spin loop, waiting for a lock to be released, will prevent other threads from making progress, so the lock will never be released. – Hot Licks Dec 03 '13 at 01:41
  • Ultimately, the version of the JDK I have source for implements Lock and ReentrantLock using sun.misc.Unsafe compareAndSwap operations. – Hot Licks Dec 03 '13 at 01:43
  • @HotLicks What is `compareAndSwap` in this case? – Mathew Kurian Dec 03 '13 at 01:51
  • Google it. It's a standard low-level synchronization mechanism. – Hot Licks Dec 03 '13 at 02:45

1 Answers1

1
  1. They might, but this result does not say that. Why would you think that? Either way, the synchronized statement uses monitorenter and monitorexit, which use this (or an encoding thereof) as a conditional variable, which, in turn, is different from your ReentrantLock. The reason as to why the threads always execute in different order is simply that the execution order is up to the system scheduler. The order in which threads are queued for creation is generally not the order in which they run the first time.
  2. If you trace down the Java framework code, you will find that eventually, Unsafe.park is called, whose implementation is system-dependent. That means, unless someone can produce an official Java document stating the implementation policies, we don't know if it uses "busy waiting" (loop until lock is available), wait-notify or a mixture of the two, and it might (and it probably does) vary between different systems and Java versions.
  3. Your sum is not always correct because you have a race condition because synchronized and lock() are locking against different semaphores. Specifically, thread 1 and 2 are synchronized among each other, but not with 3 and 4. Because you have two synchronized increments, you will always see at least two increments (thus the sum is always at least 22).
Community
  • 1
  • 1
Domi
  • 22,151
  • 15
  • 92
  • 122
  • Thank you for the explaination. Basically regarding the `while` loop, I have added a simple class showing what I think synchronized is really doing. Can you confirm if that is the internal method? – Mathew Kurian Dec 03 '13 at 00:59
  • @mk1 That new test case uses neither `ReentrantLock` nor `synchronized`. Not sure what your point is? And no that is certainly not how `synchronized` works. I added some more info about that to my answer. – Domi Dec 03 '13 at 01:03
  • That was my point. I did not know how `synchronized` worked internally. So, I put something of the way I think it might work, so I just wanted to you to tell if it worked differently than the way I expected. – Mathew Kurian Dec 03 '13 at 01:04
  • I understand it uses `monitorenter`. But I mean when you come to the nitty gritty of all these opcodes, what else can it do other than wait to see if a flag as been set on or off while in a `while` loop, which is essentially what I just did there in the class above with `Safe`. – Mathew Kurian Dec 03 '13 at 01:09
  • @mk1 read [the link](http://www.vmth.ucdavis.edu/incoming/Jasmin/ref--44.html) I just added. Also, as I said before: Whether it is a [busy-wait](http://en.wikipedia.org/wiki/Busy_waiting) (like your `Safe` class) or a wait/notify or a hybrid locking mechanism depends on the system implementation and might vary from OS to OS and version to version. – Domi Dec 03 '13 at 01:09
  • @Dormi What do you mean `busy-wait` or `wait/notify`? In the link you put up, please look at the line `waiting for the other thread to unlock the object.` Basically, this can only be done with polling a lock variable (which again is a while loop). Am I in the right direction or completely wrong? – Mathew Kurian Dec 03 '13 at 01:12
  • @mk1 Your `Safe` class uses ["busy waiting"](http://en.wikipedia.org/wiki/Busy_waiting) (loop until lock is available). The alternatives are [wait-notify](http://stackoverflow.com/questions/886722/how-to-use-wait-and-notify-in-java) or a mixture of the two (hybrid). – Domi Dec 03 '13 at 01:14