62,617
社区成员
发帖
与我相关
我的任务
分享
public class KeyLock<K> {
// 保存所有锁定的KEY及其信号量
private final ConcurrentMap<K, Semaphore> map = new ConcurrentHashMap<K, Semaphore>();
// 保存每个线程锁定的KEY及其锁定计数
private final ThreadLocal<Map<K, LockInfo>> local = new ThreadLocal<Map<K, LockInfo>>() {
@Override
protected Map<K, LockInfo> initialValue() {
return new HashMap<K, LockInfo>();
}
};
/**
* 锁定key,其他等待此key的线程将进入等待,直到调用{@link #unlock(K)}
* 使用hashcode和equals来判断key是否相同,因此key必须实现{@link #hashCode()}和
* {@link #equals(Object)}方法
*
* @param key
*/
public void lock(K key) {
if (key == null)
return;
LockInfo info = local.get().get(key);
if (info == null) {
Semaphore current = new Semaphore(1);
current.acquireUninterruptibly();
Semaphore previous = map.put(key, current);
if (previous != null)
previous.acquireUninterruptibly();
local.get().put(key, new LockInfo(current));
} else {
info.lockCount++;
}
}
/**
* 释放key,唤醒其他等待此key的线程
* @param key
*/
public void unlock(K key) {
if (key == null)
return;
LockInfo info = local.get().get(key);
if (info != null && --info.lockCount == 0) {
info.current.release();
map.remove(key, info.current);
local.get().remove(key);
}
}
/**
* 锁定多个key
* 建议在调用此方法前先对keys进行排序,使用相同的锁定顺序,防止死锁发生
* @param keys
*/
public void lock(K[] keys) {
if (keys == null)
return;
for (K key : keys) {
lock(key);
}
}
/**
* 释放多个key
* @param keys
*/
public void unlock(K[] keys) {
if (keys == null)
return;
for (K key : keys) {
unlock(key);
}
}
private static class LockInfo {
private final Semaphore current;
private int lockCount;
private LockInfo(Semaphore current) {
this.current = current;
this.lockCount = 1;
}
}
}
int hash = key.hashCode();
lock.lock(hash);
try {
//do something
} finally {
lock.unlock(hash);
}
[/quote]
没看懂。。解决了啥问题?[/quote]
key只用实现hashCode方法就行,意思是用int值对key进行映射,然后锁其int值
int hash = key.hashCode();
lock.lock(hash);
try {
//do something
} finally {
lock.unlock(hash);
}
[/quote]
没看懂。。解决了啥问题?
int hash = key.hashCode();
lock.lock(hash);
try {
//do something
} finally {
lock.unlock(hash);
}
class LockKey {
private int iKey;
private int iType;
private LockKey (int key, int type) {
iKey = key;
iType = type;
}
public static getIDLockKey (int key) {
return new LockKey(key, 0);
}
public static getBillLockKey (int key) {
return new LockKey(key, 1);
}
public int getKey() {
return iKey;
}
public boolean equals (Object o) {
if (o == null || !o instanceof LockKey)
return false;
return ((LockKey) o).iKey == iKey && ((LockKey) o).iType == iType;
}
public int hashCode() {
return iKey * 17 + (iKey << iType) * 17;
}
}
如此就可以公用KeyLock啦public class Father {
public static void main(String args[]) {
new Thread(new Runnable() {
@Override
public void run() {
MyLock strongLock = new MyLock();
WeakReference<MyLock> weakLock = new WeakReference<MyLock>(strongLock);
strongLock.lock();
System.out.println("locked");
strongLock = null;
System.out.println("Allocation like crazy");
List<String> garbage = new ArrayList<String>();
for (int i = 0; i < 1000000; i++) {
garbage.add(String.valueOf(i));
}
System.out.println("calling gc");
System.gc();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
//ignore
}
MyLock lock = weakLock.get();
if (lock == null) {
System.out.println("damn!");
return;
}
else {
lock.unlock();
}
garbage.clear();
System.out.println("Allocation like crazy again");
for (int i = 1000000; i < 2000000; i++) {
garbage.add(String.valueOf(i));
}
System.out.println("calling gc");
System.gc();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// ignore
}
if (weakLock.get() == null)
System.out.println("hooray!!");
}
}).start();
}
private static class MyLock extends ReentrantLock {
@Override
public void finalize() {
System.out.println("Hi this is me, a lock! But I'm dying, see ya");
}
}
}
测试结果:
locked
Allocation like crazy
Hi this is me, a lock! But I'm dying, see ya
calling gc
damn!
证明Lock即便被线程拥有也会被回收(看来我之前估计得没错。。)
/**
* 锁定多个key
* 建议在调用此方法前先对keys进行排序,使用相同的锁定顺序,防止死锁发生
* @param keys
*/
public void lock(K[] keys) {
if (keys == null)
return;
for (K key : keys) {
lock(key);
}
}
分别请求两个key的锁,而不是将Integer[]作为请求的锁[/quote]
楼上