All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.zon_g.ABC.client.locks.ReadWriteLock Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
/**
 * Copyright 2021 the original author, Lin Tang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.github.zon_g.ABC.client.locks;

import io.github.zon_g.ABC.client.properties.ClientProperties;
import io.github.zon_g.ABC.client.sender.RequestSender;
import io.github.zon_g.ABC.commons.request.LockRequest;
import io.github.zon_g.ABC.commons.request.UnlockRequest;
import io.github.zon_g.ABC.commons.response.Response;
import io.github.zon_g.ABC.commons.types.LockType;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * {@link ReadWriteLock} provides a {@link ReadLock} ( inclusive ) and a {@link WriteLock} ( exclusive ).
 * 

* Implementation Considerations *

* {@link ReadLock} of {@link ReadWriteLock} is inclusive, which implies that ReadLock shared * the lock, allowing all threads, acquiring the ReadLock to access the shared resource together * without modifying shared resource. While {@link WriteLock} of {@link ReadWriteLock} is exclusive. It can * inferred that only one thread can acquire a WriteLock at a time. Multiple threads will never * acquire a WriteLock until current WriteLock is released. *

* Support for Downgrade *

* {@link ReadWriteLock} supports that a WriteLock can downgrades to a ReadLock. * For example, if current thread acquires a WriteLock successfully and has not released that * lock yet, then *

    *
  1. Any other thread, which tries to acquire a WriteLock, will fails.
  2. *
  3. Any other thread, which tries to acquire a ReadLock, will fails.
  4. *
* But, if current thread tries to acquire a ReadLock, it will succeeds. At that time, current * thread holds a WriteLock and ReadLock simultaneously. If WriteLock * is released, then current thread holds only a ReadLock. Then it can be saying that a * WriteLock downgrades to a ReadLock. For example, *

*

 *     {@code
 *     ReadWriteLock lock = new ReadWriteLock("...");
 *     ReadWriteLock.ReadLock readLock = lock.readLock();
 *     ReadWriteLock.WriteLock writeLock = lock.writeLock();
 *
 *     ...
 *     writeLock.lock();
 *     ...
 *     readLock.lock();
 *     ...
 *     writeLock.unlock(); // WriteLock downgrades to ReadLock
 *     ...
 *     readLock.unlock();
 *     ...
 *
 *     }
 * 
*

* No Support for Reentrant Usage *

* Current {@link ReadWriteLock} does not support for reentrant usage, indicating that if one thread * acquires a ReadLock or a WriteLock successfully, then invocation of * {@link ReadLock#tryLock()}, {@link ReadLock#lock()}, {@link WriteLock#tryLock()} or {@link WriteLock#lock()} * fails immediately. * * @author Lin Tang * @see ReadLock * @see WriteLock * @since 1.0.0 */ public class ReadWriteLock extends Lock { private static final Logger logger = Logger.getLogger(ReadLock.class.getName()); private static final RequestSender sender = RequestSender.getSender(); private static final ClientProperties properties = ClientProperties.getProperties(); ReadWriteLock(String lockKey) { super(lockKey); } public ReadLock readLock() { return new ReadLock(this.getLockKey()); } public WriteLock writeLock() { return new WriteLock(this.getLockKey()); } @Override protected boolean tryLock() { return false; } @Override protected void lock() { } @Override protected void unlock() { } @SuppressWarnings("all") public class ReadLock extends Lock { ReadLock(String lockKey) { super(lockKey); } @Override public boolean tryLock() { if (!this.validateLockKey()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, EMPTY_LOCK_KEY); } return false; } if (!this.canLock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_ALREADY); } return false; } LockRequest request = new LockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, true, false); final Response response; final RequestSender requestSender = sender.clone(); if ((response = requestSender.sendRequest(request)).isSuccess()) { this.setCanLock(false); this.setCanUnlock(true); this.setSuccess(true); } return response.isSuccess(); } @Override public void lock() { if (!this.validateLockKey()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, EMPTY_LOCK_KEY); } return; } if (!this.canLock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_ALREADY); } return; } LockRequest request = new LockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, false, false); final RequestSender requestSender = sender.clone(); requestSender.sendRequest(request); this.setCanLock(false); this.setCanUnlock(true); this.setSuccess(true); } @Override public void unlock() { if (!this.isSuccess()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_FAILS); } return; } if (!this.canUnlock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, UNLOCKING_ALREADY); } return; } UnlockRequest request = new UnlockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, false); final RequestSender requestSender = sender.clone(); if (requestSender.sendRequest(request).isSuccess()) this.setCanUnlock(false); } } @SuppressWarnings("all") public class WriteLock extends Lock { WriteLock(String lockKey) { super(lockKey); } @Override public boolean tryLock() { if (!this.validateLockKey()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, EMPTY_LOCK_KEY); } return false; } if (!this.canLock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_ALREADY); } return false; } LockRequest request = new LockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, true, true); final Response response; final RequestSender requestSender = sender.clone(); if ((response = requestSender.sendRequest(request)).isSuccess()) { this.setCanLock(false); this.setCanUnlock(true); this.setSuccess(true); } return response.isSuccess(); } @Override public void lock() { if (!this.validateLockKey()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, EMPTY_LOCK_KEY); } return; } if (!this.canLock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_ALREADY); } return; } LockRequest request = new LockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, false, true); final RequestSender requestSender = sender.clone(); requestSender.sendRequest(request); this.setSuccess(true); this.setCanLock(false); this.setCanUnlock(true); } @Override public void unlock() { if (!this.isSuccess()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, LOCKING_FAILS); } return; } if (!this.canUnlock()) { if (logger.isLoggable(Level.INFO)) { logger.log(Level.INFO, UNLOCKING_ALREADY); } return; } UnlockRequest request = new UnlockRequest(this.getLockKey(), properties.getApplication(), Thread.currentThread().getName(), LockType.ReadWriteLock, true); final RequestSender requestSender = sender.clone(); if (requestSender.sendRequest(request).isSuccess()) this.setCanUnlock(false); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy