Using integers as Java Locks

Asked

Viewed 77 times

4

I have the following code snippet:

class classe{
    public static void main(String[] args){
        Integer lock = 0;

        Thread t1 = new Thread(){
            public void run(){
                // instruções thread sem sincronia
                synchronized(lock){
                    //instruções sincronizadas
                }
                // instruções thread sem sincronia
            }
        }

        Thread t2 = new Thread(){
            public void run(){
                // instruções thread sem sincronia
                synchronized(lock){
                    //instruções sincronizadas
                }
                // instruções thread sem sincronia
            }
        }

        t1.start();
        t2.start();

    }
}

I would like to know how the variable works lock as whole in that code snippet, what happens to it when it enters the block synchronized.

What I need in my program is that when the first thread starts executing one part of an instruction block, the other is locked when arriving in a block synchronized related to the first.

EDIT: Making clearer the problem I have, I need to communicate several threads that will run at the same time using Wait() and notify(), the example below better exemplifies the problem:

class classe{
        public static void main(String[] args){
            Integer lock1 = new Integer(0);
        Integer lock2 = new Integer(1);

            Thread t1 = new Thread(){
                public void run(){
                    // instruções thread sem sincronia
                    synchronized(lock1){
                        //instruções sincronizadas
                    lock1.notify();
                    }
                    // instruções thread sem sincronia
                }
            }

            Thread t2 = new Thread(){
                public void run(){
                    // instruções thread sem sincronia
                    synchronized(lock1){
                        //instruções sincronizadas
                    while(condicao)
                        lock1.wait();
                    }
                    // instruções thread sem sincronia
                }
            }

        Thread t3 = new Thread(){
                public void run(){
                    // instruções thread sem sincronia
                    synchronized(lock2){
                        //instruções sincronizadas
                    while(condicao)
                        lock2.wait();
                    }
                    // instruções thread sem sincronia
                }
            }

            t1.start();
            t2.start();
        t3.start();

        }
    }

By my understanding of the above program, while thread 1 and thread 2 are synchronized, thread 3 can be run independently of both. The thinking is right?

  • 1

    Yes, thread 3 is "independent" because it uses a different lock than 1 and 2 (these in turn use the same lock and are synchronized). But there is no reason to use Integer, could be two Object even

  • I don’t do much with the Wait() and notify() primitives so I can’t be sure the syntax is correct, the code looks ok but I’m not seeing lock2.notify() code anywhere to notify thread 3, it will sleep indefinitely. But I think it’s better instead of you describing a possible solution describe your problem and we see how it could be solved.

  • On another question in the case.

2 answers

3

The Integer in that case it is not treated as anything in particular other than being an object. So much so that it could be a Object in his stead.

Virtually any object can be used as lock for blocks synchronized. You are doing right, which is to lock based on the same object in the two blocks. Execution will take place as desired.

If you were thinking that the Integer was incremented or something, maybe he was looking for Reentrantlock. But I believe it’s not for your case.

3

What happens to the Integer is the same as with any object you pass to the statement synchronized. According to the language specification, when you do synchronized(expressão), happens the following:

  • The expression is evaluated
  • if the evaluation is interrupted for some reason (because it may be for example a method call that returns the lock, and this call may give error), the statement is also interrupted
  • otherwise, if the value of the expression is null, is launched a NullPointerException
  • otherwise, consider that the value of the expression is V. The thread running the block synchronized gives a lock in the monitor associated with V
  • The block is executed
    • if the execution is completed, there is the release (Unlock) monitor
    • if the execution is interrupted for some reason, the Unlock, but the block synchronized is also interrupted

I mean, there’s nothing special about using Integer there. It could be even any object (Object lock = new Object()) there would be no problem. This object serves only as an "indication": if two blocks use the same object as lock, this indicates that two threads cannot run those blocks at the same time. It does not matter if this object is a Integer, Object, or whatever.


By my understanding of the above program, while thread 1 and thread 2 are synchronized, thread 3 can be run independently of both. The thinking is right?

Yes, that’s correct: the threads t1 and t2 are synchronized with each other as they both use the same lock. In the case, t2 flame lock1.wait() , then she stands still, until t1 calling lock1.notify().

Already t3, for using a lock different, performs independent of t1 and t2 (although in her example she is waiting indefinitely, since there is no other thread that calls lock2.notify()).

Anyway, there’s no reason to use Integer. You could just use two Object's:

Object lock1 = new Object();
Object lock2 = new Object();

So you don’t worry about creating instances of Integer with different values. Using Object, you already guarantee that the Locks will be different.


There is another detail there (not directly related to Locks in itself): what happens if t1 call for notify before t2 call for wait? In this case, t2 will not be notified as she was not yet standing by waiting for someone to notify her, so she will be waiting indefinitely (unless, of course, some other thread calls notify or notifyAll in lock1).

To avoid this situation, you can call wait(timeout), passing the amount of milliseconds the thread will be waiting for (if that time runs out, it stops waiting). For example, for the thread to wait at most for 3 seconds, use lock1.wait(3000).

  • The question especially to use the integer, is in the case of using two different variables with the same integer value. They do not become the same lock, in this case?

  • 1

    First, it has to be an object Integer, one int primitive does not serve (nor compiles). The object has to be the same (lock1 == lock2 return true), cannot be for example two integers with the same value. But coincidentally it should work because there is a pool of Integers of small value for memory saving purposes, so it may be that the same object can be reused.

  • But only testing to know.

  • @DJM_JM As soon as I can I make a test and confirm (but today I may not be able)

  • Anyway, my guess (no testing) is that @Piovezan is right :-)

  • I edited the initial post and took the opportunity to put a more accurate situation than I need.

  • @DJM_JM I updated the answer

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.