0

I wanted to ask if this implementation is ok, or maybe there are some issues that can be later problematic.

The idea is to implement a ReentrantLock class that can be used with 'try with resources' and that means that it has to implement the AutoCloseable interface.

In addition, I wanted to ask why in the 'main' method the compiler yields that I have to add a 'catch' clause, because my close method (in MyReentrantLock) doesn't throw an exception.

import java.util.concurrent.locks.ReentrantLock;

public class Ex09ReentrantLock {

    @SuppressWarnings("serial")
    public static class MyReentrantLock extends ReentrantLock implements AutoCloseable{

        public MyReentrantLock() {
            super();
            lock();
        }

        @Override
        public void close(){        
            unlock();
        }   
    }

    public static AutoCloseable lock() {

        var locker = new MyReentrantLock(); //lock() is called in the constructor

        return locker;  //implements AutoCloseable          
    }


    //Demo 
    public static void main(String[] args) {

        //try(ReentrantLock lock = new ReentrantLock()){} = compiler error

        try(var locker = lock();){          
            //some work...          
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
    }
}
  1. Is this implementation ok? (call the lock in the constructor...)

  2. Why does the compiler force me to add a catch() clause if my close doesn't throw an exception?

geisterfurz007
  • 5,292
  • 5
  • 33
  • 54
  • To answer your second question: It forces you to catch `Exception` because your `#lock()` method returns `AutoCloseable` whose `#close()` method _does_ declare itself to throw the mentioned exception. Since the declared type that's returned is `AutoCloseable` the compiler has no idea the _implementation_ doesn't have a throws declaration. Your method would have to return `MyReentrantLock` for the compiler to know such information. – Slaw Dec 02 '19 at 09:38

1 Answers1

1

Locks are meant to be shared. A lock that locks on construction can only be locked using new and thus isn't shareable meaning its useless.

I believe your sample code is for illustration purpose only (but if not, it is definitely a bad idea), to help you more a real case should be given.

Guessing from what you shared, what's closest to what you expressed is the synchronized keyword.

In general, locks interactions are difficult to handle, which led to the creation of the synchronized mechanism. Using locks instead should be done in very specific situations where synchronization isn't possible.

Antoine Marques
  • 1,379
  • 1
  • 8
  • 16
  • Just to note, in regards to your last paragraph, in Java the `synchronized` mechanism actually predates `Lock` (added in Java 5). If I recall correctly, for a while there the `Lock` API actually performed significantly better under contention but I believe that is no longer true in newer versions (no sources on hand). – Slaw Dec 02 '19 at 09:35
  • Not sure if i understand correctly what you mean, but `synchronized` uses monitor locks (implemented natively) which is different from the lock API which is a high level. I once built a `Lock` using monitors to be able to use `synchronized` mechanism via Lock API using a somewhat hidden feature enabling to manually enter or exit an object's intrinsic lock. – Antoine Marques Dec 02 '19 at 10:57
  • Your last paragraph implies, to me, that `synchronized` was created in response to some failings/difficulties of `Lock`. Now, maybe you're referencing programming history in general, but in Java `Lock` was added many versions after `synchronized`. I'm pretty sure `Lock` was added to provide functionality for which `synchronized` is incapable of providing. And my second sentence was relating some benchmarks I remember reading about; when first added, the `Lock` API performed better, under contention, than `synchronized`—but I believe they've matched each other in recent versions of Java. – Slaw Dec 02 '19 at 11:09
  • Ok thanks, i know understand what predates mean in this case. – Antoine Marques Dec 02 '19 at 11:19
  • Sure, you're right. Monitor locks are used by low level API for concurrency implementation, for example java.concurrent package implementation. Locks are more of a high level object. Synchronized keyword was high level 'safe' access to low level functionnalities such as Objet.wait/notify. – Antoine Marques Dec 02 '19 at 11:21
  • For the record, monitor locks may be wrapped inside a Lock class using http://www.docjar.com/docs/api/sun/misc/Unsafe.html – Antoine Marques Dec 02 '19 at 11:22