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

io.github.icodegarden.nutrient.lang.concurrent.lock.DatabaseReadWriteLock Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show newest version
package io.github.icodegarden.nutrient.lang.concurrent.lock;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

import org.springframework.util.Assert;

import io.github.icodegarden.nutrient.lang.concurrent.lock.DatabaseReadWriteLockRepository.LockDO;
import io.github.icodegarden.nutrient.lang.util.SystemUtils;

/**
 * 
 * @author Fangfang.Xu
 *
 */
public abstract class DatabaseReadWriteLock implements DistributedLock {

	private final boolean readType;

	private final String identifier;

	private final DatabaseReadWriteLockRepository lockRepository;

	private final String name;
	private final Long expireSeconds;

	private long acquireIntervalMillis = 500;

	public DatabaseReadWriteLock(DatabaseReadWriteLockRepository lockRepository, String name, String identifier, Long expireSeconds,
			boolean readType) {
		Assert.hasText(name, "name must not empty");
		Assert.isTrue(name.length() <= 50, "name length must <= 50");

		this.lockRepository = lockRepository;
		this.identifier = identifier;
		this.name = name;
		this.expireSeconds = expireSeconds;
		this.readType = readType;
	}

	public void setAcquiredIntervalMillis(long acquireIntervalMillis) {
		Assert.isTrue(acquireIntervalMillis > 0, "acquireIntervalMillis must gt 0");
		this.acquireIntervalMillis = acquireIntervalMillis;
	}

	@Override
	public boolean isAcquired() throws LockException {
		try {
			String nowStr = SystemUtils.STANDARD_DATETIME_FORMATTER.format(SystemUtils.now());
			List list = lockRepository.listLockedDataInterProcess(name, identifier, readType, nowStr);
			if (list.isEmpty()) {
				return false;
			}
			return list.stream().anyMatch(one -> one.getIdentifier().equals(identifier) && one.isReadType() == readType);
		} catch (Exception e) {
			throw new LockExceedExpectedException(e);
		}
	}

	@Override
	public void acquire() throws LockException {
		acquire(Long.MAX_VALUE);
	}

//获取读锁->
//	检查本地是否已获取->
//		是->成功+1
//		否->获取锁名称所有lock条数->
//			检查是否有wirte锁->
//				是->write锁是否本地持有的-》
//					是->成功,写入read锁
//					否-》失败
//				否->写入read锁
//					
//释放读锁->删除对应lock数据	
//
//获取写锁->
//    检查本地是否已获取->
//		是-》成功+1
//		否-》获取锁名称所有lock条数->
//			检查是否有任何锁-》
//				是-》失败
//				否-》写入write锁
//				
//释放写锁-》删除对应lock数据					
	@Override
	public boolean acquire(long timeoutMillis) throws LockException {
		LocalDateTime start = SystemUtils.now();
		for (;;) {
			try {
				boolean b = mutex();
				if (!b) {
					lockRepository.createRow(name, identifier, expireSeconds,
							SystemUtils.STANDARD_DATETIME_FORMATTER.format(SystemUtils.now()), readType);
					return true;
				}

				if (SystemUtils.now().minus(timeoutMillis, ChronoUnit.MILLIS).isAfter(start)) {
					return false;
				}
			} catch (Exception e) {
				throw new LockExceedExpectedException(e);
			}
			sleep();
		}
	}

	private boolean mutex() {
		String nowStr = SystemUtils.STANDARD_DATETIME_FORMATTER.format(SystemUtils.now());
		List dos = lockRepository.listLockedDatas(name, nowStr);
		if (this.readType) {
			/**
			 * 是否有write锁且不是本地持有的
			 */
			boolean b = dos.stream().anyMatch(one -> {
				return !one.isReadType() && !identifier.equals(one.getIdentifier());
			});

			return b;
		} else {
			/**
			 * 是否有任何锁
			 */
			boolean b = !dos.isEmpty();
			return b;
		}
	}

	@Override
	public void release() throws LockException {
		try{
			lockRepository.deleteRow(name, identifier);
		} catch (Exception e) {
			throw new LockExceedExpectedException(e);
		}
	}

	private void sleep() throws LockInterruptedException {
		try {
			Thread.sleep(acquireIntervalMillis);
		} catch (InterruptedException e) {
			throw new LockInterruptedException(e);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy