package com.sinata.rest.common.lock;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executors;
|
|
public class IdLocker {
|
|
public static Object simpleLock(Integer id) {
|
return id.toString().intern();
|
}
|
|
private ConcurrentHashMap<Integer, IdLock> locks = new ConcurrentHashMap<>();
|
|
public IdLock acquireLock(Integer userId) {
|
IdLock lock = locks.get(userId);
|
if (lock == null) {
|
synchronized (this) {
|
lock = locks.get(userId);
|
if (lock == null) {
|
lock = new IdLock(userId);
|
locks.put(userId, lock);
|
}
|
}
|
}
|
synchronized (lock) {
|
//如果是初始值,则设置为1,表示当前获得锁的数量为1
|
if (lock.count.get() == Integer.MAX_VALUE) {
|
lock.count.set(1);
|
} else {
|
//当数量不为0,标识锁还有效
|
if (lock.count.get() != 0) {
|
//获得锁的将持有者数量加1
|
lock.count.addAndGet(1);
|
}
|
}
|
}
|
//当数量为0,标识锁已经被弃用,需要重新创建并获得
|
if (lock.count.get() == 0) {
|
return acquireLock(userId);
|
}
|
return lock;
|
}
|
|
public void locked(Integer id, Runnable runnable) {
|
IdLock lock = acquireLock(id);
|
try {
|
synchronized (lock) {
|
runnable.run();
|
}
|
releaseLock(lock);
|
} catch (Exception e) {
|
releaseLock(lock);
|
throw e;
|
}
|
}
|
|
public void releaseLock(IdLock lock) {
|
//用完锁要释放,内存
|
synchronized (lock) {
|
lock.count.getAndAdd(-1);
|
if (lock.count.get() == 0) {
|
synchronized (this) {
|
locks.remove(lock.getId());
|
}
|
}
|
}
|
}
|
|
static class TestHolder {
|
int count = 0;
|
}
|
|
public static void main(String[] args) {
|
System.out.println("Printer");
|
TestHolder countA = new TestHolder();
|
TestHolder countB = new TestHolder();
|
int idA = 3;
|
int idB = 4;
|
IdLocker locker = new IdLocker();
|
ExecutorService executor = Executors.newCachedThreadPool();
|
for (int i = 0; i < 50000; i++) {
|
executor.execute(() -> {
|
IdLock lock = locker.acquireLock(idA);
|
synchronized (lock) {
|
countA.count++;
|
}
|
locker.releaseLock(lock);
|
});
|
if (i < 50) {
|
new Thread(() -> {
|
IdLock lock = locker.acquireLock(idA);
|
synchronized (lock) {
|
countA.count++;
|
}
|
locker.releaseLock(lock);
|
}).start();
|
}
|
}
|
for (int i = 0; i < 70000; i++) {
|
executor.execute(() -> {
|
IdLock lock = locker.acquireLock(idB);
|
synchronized (lock) {
|
countB.count++;
|
}
|
locker.releaseLock(lock);
|
});
|
}
|
try {
|
Thread.sleep(5000);
|
System.out.println("A = " + countA.count);
|
System.out.println("B = " + countB.count);
|
System.out.println("Locker = " + locker.locks.size());
|
executor.shutdown();
|
} catch (Exception e) {
|
|
}
|
}
|
|
}
|