How to use lock wrapper for autocloseable? - java

I have wrote following wrapepr:
public class AutoCloseableLockWrapper implements AutoCloseable, Lock{
private final Lock lock;
public AutoCloseableLockWrapper(Lock l) {
this.lock = l;
}
#Override
public void lock() {
this.lock.lock();
}
#Override
public void lockInterruptibly() throws InterruptedException {
lock.lockInterruptibly();
}
#Override
public boolean tryLock() {
return lock.tryLock();
}
#Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return lock.tryLock(time,unit);
}
#Override
public void unlock() {
lock.unlock();
}
#Override
public Condition newCondition() {
return lock.newCondition();
}
#Override
public void close() {
this.lock.unlock();
}
}
In my code I use it like this:
public class ReadWriteMap implements Map {
private HashMap map = new HashMap();
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private Lock readLock = readWriteLock.readLock();
private Lock writeLock = readWriteLock.writeLock();
#Override
public int size() {
try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
autoCloseableLockWrapper.lock();
return map.size();
}
}
#Override
public boolean isEmpty() {
try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
autoCloseableLockWrapper.lock();
return map.isEmpty();
}
}
#Override
public boolean containsKey(Object key) {
try (AutoCloseableLockWrapper autoCloseableLockWrapper = new AutoCloseableLockWrapper(readLock)) {
autoCloseableLockWrapper.lock();
return map.containsKey(key);
}
}
...
}
I don't want to create wrapper in each method.
Is there way to combine single wrapper and try with resources ?

You are over-complicating your design. If your AutoCloseableLockWrapper intentionally exposes all operations supported by the underlying Lock, there is no point in making it private and adding delegation methods for each of Lock’s methods. You could simply make the Lock reference public to allow its use, or leave it off entirely, as the code which creates the wrapper already has a reference to the Lock.
All you want to do, is to support a single operation, unlock, which should be viewed as AutoCloseable.
A Java 8 solution may look like
import java.util.concurrent.locks.Lock;
public interface AutoUnlock extends AutoCloseable {
public static AutoUnlock lock(Lock lock) {
lock.lock();
return lock::unlock;
}
#Override
public void close(); // no checked exceptions
}
It can be used like:
Lock lock=…
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
// critical code
}
// …
try(AutoUnlock u=AutoUnlock.lock(lock)) {
// critical code
}
If you worry about the instance creation (usually this is not an issue), you can re-use AutoCloseables:
AutoUnlock reusable=lock::unlock;
// …
lock.lock();
try(AutoUnlock u=reusable) {
// critical code
}
// …
lock.lock();
try(AutoUnlock u=reusable) {
// critical code
}
To me, it looks less clear since the lock(); and try statements are not syntactically coupled and could be separated by accident. But if the lock has a non-local scope, you could solve this by creating a utility method:
final Lock lockInstance; // this field name is to prevent confusion with the lock() method
final AutoUnlock reusable;
YourConstructor(Lock lock) {// you may get the Lock as a parameter
lockInstance=lock; // or create one here, right in the constructor
reusable=lockInstance::unlock;
}
AutoUnlock lock() {
lockInstance.lock();
return reusable;
}
void doSomething() {
// …
try(AutoUnlock u=lock()) {
// critical code
}
// …
try(AutoUnlock u=lock()) {
// critical code
}
}
I think, it’s not too hard to back-port this logic into Java 7 code, if needed.

You can use a factory method that returns a singleton. Nothing is forcing you to use a constructor.
BTW you should not call lock inside the try-block. That should have already happened in the "acquire the resource" phase (within the constructor in your current design, inside the factory method in my proposal).
I see that the above note is already posted on the Q&A page where you contributed your wrapper. The page already has very good content; I advise to study it well.

I'd prefer just creating a new lock (not a wrapper around a lock):
public class AutoReentrantLock implements AutoCloseable {
private final ReentrantLock lock = new ReentrantLock();
public AutoReentrantLock lock() {
lock.lock();
return this;
}
public void earlyUnlock() {
lock.unlock();
}
#Override
public void close() {
if(lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
Use like this:
private AutoReentrantLock consistencyLock = new AutoReentrantLock();
try(AutoReentrantLock lock = consistencyLock.lock()) {
// other code
}
Or a more complicated use case, where you unlock halfway:
private AutoReentrantLock consistencyLock = new AutoReentrantLock();
try(AutoReentrantLock lock = consistencyLock.lock()) {
// Place code here that gathers information (while under lock)
// but may exit early or throw exceptions
lock.earlyUnlock();
// ... followed by code that is slow that acts upon above gathered information.
}

Related

Concurrent-safe queue in Java

I'm trying to create thread safe queue with unique elements. I see no vulnerabilities but not sure still is this realisation thread safe or not? get(), add(), toArray() methods do everything under lock, toString() and equals() use toArray() in order to get main array copy and work independently with copy without locks.
public class SafeQueue<T> {
private final Object[] queue;
private final HashSet<T> content;
private final Lock lock;
private int size;
public SafeQueue() {
queue = new Object[100];
content = new HashSet<>(100);
lock = new ReentrantLock();
}
public boolean add(T el) {
Objects.requireNonNull(el);
final Lock lock = this.lock;
lock.lock();
try {
//some logic
} finally {
lock.unlock();
}
return true;
}
public T get() {
final Lock lock = this.lock;
lock.lock();
try {
T el = (T) queue[0];
if (el != null) {
//some shift logic
content.remove(el);
}
return el;
} finally {
lock.unlock();
}
}
public Object[] toArray() {
final Lock lock = this.lock;
lock.lock();
try {
return Arrays.copyOf(this.queue, size);
} finally {
lock.unlock();
}
}
#Override
public boolean equals(Object o) {
Object[] eqQueue = ((SafeQueue<?>) o).toArray();
Object[] curQueue = toArray();
//some comparison logic with eqQueue and curQueue
return equal;
}
#Override
public String toString() {
Object[] curQueue = toArray();
StringBuilder sb = new StringBuilder();
sb.append('[');
//some logic with curQueue
return sb.toString();
}
}
You might want to ask, what does it mean for the equals method to be thread safe? Consider this:
SafeQueue<T> qa = ...;
SafeQueue<T> qb = ...;
...
if (qa.equals(qb)) {
handleEqualsCase();
}
If you had any reason to worry about the thread-safety of the equals() method, that could only be because other threads potentially could modify either queue when equals() is called.
But, by the time handleEqualsCase() is called, those other threads still could be running, and now, neither qa nor qb is locked. There is no guarantee that the two queues still will be equal when handleEqualsCase() is called. But, if they're not equal, that must be a Bad Thing, right? Otherwise, why would you have bothered to test for equality in the first place?
Here's one way around that problem. Instead of writing a traditional equals() method, write something like this instead:
private static
boolean unsynchronizedEqualityTest(SafeQueue<T> qa, SafeQueue<T> qb) {
...
}
public static
void doIfEqual(SafeQueue<T> qa, SafeQueue<T> qb, Runnable handler) {
qa.lock.lock();
qb.lock.lock();
try {
if (unsynchronizedEqualityTest(qa, qb)) {
handler.run();
}
} finally {
qb.lock.unlock();
qa.lock.unlock();
}
}
Now, when the client-supplied handler is invoked, it's guaranteed that the two queues still will be equal because they're both still locked.
But BEWARE! There's potential for a deadlock if one thread calls doIfEqual(qa,qb,...) and another thread calls doIfEqual(qb,qa,...). I'll leave it to you to figure out how to prevent that deadlock from happening.
Yes, your implementation is thread safe.

How to avoid concurrent execution of two methods?

I have two synchronized methods, each of them is being executed by a different Thread.
public synchronized ResultSet dbExecuteQuery(String queryStmt);
public synchronized void dbExecuteUpdate(String queryStmt);
How can I make sure their execution won't "overlap"?
One solution that comes to my mind is the following:
public synchronized ResultSet dbExecute(String queryStmt, boolean isUpdate) {
if (isUpdate) {
dbExecuteUpdate(queryStmt);
return null;
} else
return dbExecuteQuery(queryStmt);
}
But it means I would have to change all code used in the whole project. Is there a cleaner way to do it?
You can add a dedicated synchronization object:
class YourClass {
Object syncObject = new Object();
public ResultSet dbExecuteQuery(String queryStmt) {
synchronized(syncObject) {
// your code
}
}
public void dbExecuteUpdate(String queryStmt) {
synchronized(syncObject) {
// other code
}
}
}
But it's probably better to use a ReentrantLock.
class YourClass {
private Lock lock = new ReentrantLock();
public ResultSet dbExecuteQuery(String queryStmt) {
lock.lock();
// your code
lock.unlock();
}
public void dbExecuteUpdate(String queryStmt) {
lock.lock();
// other code
lock.unlock();
}
}
Actually, since one is a read and one a write, you probably want to use ReadWriteLock.
class YourClass {
private ReadWriteLock lock = new ReentrantReadWriteLock();
public ResultSet dbExecuteQuery(String queryStmt) {
lock.readLock().lock();
// your code
lock.readLock()..unlock();
}
public void dbExecuteUpdate(String queryStmt) {
lock.writeLock()..lock();
// other code
lock.writeLock().unlock();
}
}
This way you can have several threads reading concurrently:
The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

Convert double check locking from using synchronized to locks in JAVA

Consider the following code implementing double check locking using the synchronized keyword in JAVA 8:
private static void redoHeavyInitialisation() {
if (needToReinitialise()) {
synchronized (MyClass.class) {
if (needToReinitialise()) {
doHeavyInitialisation();
}
}
}
}
The reason double check locking is used is because the initialisation is heavy (hence lazy) AND it can happen more than once (hence singleton pattern can not be used, correct me if I am wrong).
Anyway, first, how do you convert the code above to use Lock from the JAVA concurrent package instead of using synchronized keyword?
Only after that AND optionally, feel free to comment on using Lock or synchronized keyword which one is better.
Remember, this question is not about Lock vs synchronized comparison. Answer attempts without answering the code conversion part will not be picked as accepted answer.
Transformation of synchronized blocks to the equivalent block using ReentrantLock is pretty rote.
First you create a lock with the same or similar scope and lifetime as the object you were locking on. Here you are locking on MyClass.class, hence a static lock, so you can map this to a static lock in MyClass, such as MyClass.initLock.
Then just replace each:
synchronized (object) {
with
lock.lock();
try {
and each associated closing brace with
} finally {
lock.unlock();
}
Putting it all together you have:
private final static ReentrantLock initLock = new ReentrantLock();
private static void redoHeavyInitialisation() {
if (needToReinitialise()) {
MyClass.initLock.lock();
try {
if (needToReinitialise()) {
doHeavyInitialisation();
}
} finally {
MyClass.initLock.unlock();
}
}
}
Performance-wise there is little daylight between the approaches. They essentially have the same semantics and usually use similar underlying mechanisms. In the past, there have been performance differences - sometimes optimizations have gone in that affect one or the other, so on some JVMs you can find a difference, but the whole point of double checked locking is to avoid taking the lock anyway, so just do what's simplest. You only get the lock for a very small transitory period while the needToReinitialise() method is running, so the locking cost won't have any ongoing impact.
Consider the following code:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HeavyInitializer {
static final Logger logger = LoggerFactory.getLogger(HeavyInitializer.class);
static HeavyInitializer singleton;
public static synchronized HeavyInitializer getInstance() {
if (singleton==null) {
singleton = new HeavyInitializer();
}
return singleton;
}
boolean initialized;
private HeavyInitializer() {
initialized = false;
}
public synchronized void initialize() {
if (!initialized) {
heavyStuffDoneHere();
}
}
public synchronized void reInitilize() {
if (needToReinitialise()) {
heavyStuffDoneHere();
}
}
private void heavyStuffDoneHere() {
initialized = true;
}
private boolean needToReinitialise() {
if (!initialized)
return false;
boolean ret = false;
//Do your check here... and set ret
return ret;
}
}
From Oracle's doc:
... then making these methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
Trying to use Lock would be trying to reimplement the synchronized block. Not necessary.
Singleton Double checks the lock and prevents singleton object to break using serialization.
package pattern.core.java;
import java.io.Serializable;
public class Singleton extends Object implements Serializable {
private static final long serialVersionUID = 1L;
private static Singleton sg;
private Singleton() {
}
public static Singleton getSingletonObj() {
if (sg == null) {
synchronized (sg) {
if (sg == null) {
sg = new Singleton();
}
}
}
return sg;
}
/*
* this method ensures that new object will not be created for singleton
* class using serialization and deserialization
*/
protected Object readResolve() {
return sg;
}
/*
* #Override protected Object clone() throws CloneNotSupportedException {
* throw new CloneNotSupportedException(); }
*/
#Override
protected Object clone() throws CloneNotSupportedException {
return sg;
}
}

Synchronization pattern

I have a class named "Channel" with two methods defined:
class Channel {
void read(){...}
void write(){...}
}
There's an instance of this class used in multi-threaded environment. Several threads periodically read from channel while one thread periodically writes to it. Read operation is thread-safe so that it is ok for several reads to occur simultaneously. However once write operation starts, read threads must be blocked until write operation is finished. It is essential to keep read operations as fast as possible and avoid resource-consuming synchronization routines.
What would be the most appropriate pattern to implement such behaviour? Maybe java classes or libraries to help?
Use a ReadWriteLock. It will allow concurrent reads to occur with serial writes. To further satisfy your requirements, an acquisition of a writeLock will prevent any readLock's from making progress until a subsequent release.
class Channel {
final ReadWriteLock lock = new ReentrantReadWriteLock();
void read(){
lock.readLock().lock();
try{
}finally{
lock.readLock().unlock();
}
}
void write(){
lock.writeLock().lock();
try{
}finally{
lock.writeLock().unlock();
}
}
}
For fun, here's an implementation using the new Java 7 try-with-resources feature.
class RWLock {
class ACLock extends ReentrantLock implements AutoCloseable {
public void close() {
this.unlock();
}
}
private ACLock readLock = ACLock();
private ACLock writeLock = ACLock();
private int numReaders = 0
public AutoCloseable write() {
readLock.lock();
writeLock.lock();
return new AutoCloseable() {
public void close() {
writeLock.close();
readLock.close();
}
}
}
public AutoCloseable read() {
try (ACLock read = readLock.acquire()) {
if (numReaders == 0) {
writeLock.lock();
}
numReaders++;
}
return new AutoCloseable() {
public void close() {
numReaders--;
if (numReaders == 0) {
writeLock.unlock();
}
}
}
}
// Here's how you use them
public static void main(String[] args) {
RWLock lock = RWLock();
try (AutoCloseable lock = RWLock.read()) {
// Do some readin'
}
try (AutoCloseable lock = RWLock.write()) {
// Do some writin'
}
}
}

Controlling race condition at startup

I have some code that I want to have some one time initialisation performed. But this code doesn't have a definite lifecycle, so my logic can be potentially invoked by multiple threads before my initialisation is done. So, I want to basically ensure that my logic code "waits" until initialisation is done.
This is my first cut.
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
synchronized(initialised) {
initStuff();
initialised.getAndSet(true);
initialised.notifyAll();
}
}
public void doStuff() {
synchronized(initialised) {
if (!initialised.get()) {
try {
initialised.wait();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
}
}
doOtherStuff();
}
}
I basically want to make sure this is going to do what I think it's going to do -- block doStuff until the initialised is true, and that I'm not missing a race condition where doStuff might get stuck on a Object.wait() that will never arrive.
Edit:
I have no control over the threads. And I want to be able to control when all of the initialisation is done, which is why doStuff() can't call initialise().
I used an AtomicBoolean as it was a combination of a value holder, and an object I could synchronize. I could have also simply had a "public static final Object lock = new Object();" and a simple boolean flag. AtomicBoolean conveniently gave me both. A Boolean can not be modified.
The CountDownLatch is exactly what I was looking for. I also considered using a Sempahore with 0 permits. But the CountDownLatch is perfect for just this task.
That's a strange mix of library and built-in concurrency controls. Something like this is much cleaner:
public class MyClass {
private static final CountDownLatch latch = new CountDownLatch(1);
public void initialise() {
initStuff();
latch.countDown();
}
public void doStuff() {
try {
latch.await();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
doOtherStuff();
}
}
A synchronized block will automatically block other threads. Just use a simple lock object + status variable:
public class MyClass {
private static boolean initialised;
private static final Object lockObject = new Object();
public void initialise() {
synchronized (lockObject) {
if (!initialised) {
initStuff();
initialised = true;
}
}
}
public void doStuff() {
initialise();
doOtherStuff();
}
}
The best may be to use a static initializer (as mentioned by SB):
public class MyClass {
public static void doInitialize() {
...
}
public void doStuff() {
doOtherStuff();
}
static {
doInitialize();
}
}
This will get executed once before any other code is allowed to be called. If you will always have to initialize anytime the class is used then there is no performance hit as the class will not be loaded until it is used. See the answers to this question for more details.
It this is right at startup, why not wait to start the other threads until the initialization is complete?
Also, you can do a thread-synchronized IsComplete boolean that is set to false until it is set to true by the initialization routine.
You're using AtomicBoolean always from inside a synchronized block. There's not much point to that since only one thread can access it. Atomic variables are intended for use in lock-free solutions - you can get and set the value as an uninterruptable unit.
I guess you are looking for a lock free solution once the intiialization has happened:
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
if (!intialized.get())
{
synchornized (this)
{
if (!initialized.getAndSet(true))
doInitialize();
}
}
}
public void doStuff() {
initialize();
doOtherStuff();
}
You could also do this with a simple volatile boolean which is actually a little more efficient than an AtomicBoolean.

Categories