代码如下,
import java.util.HashSet; import java.util.Set; public class LockTest1 { public static Set<String> map = new HashSet<String>(); public static void testlock(String uid,String prefix) { boolean flag = false; try { if(flag=getLock(uid, prefix)) { Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" getLock success"); } else { System.out.println(Thread.currentThread().getName()+" not getLock"); } } catch (Exception e) { e.printStackTrace(); } finally { if(flag)removeLock(uid, prefix); } } public static void testlock2(String uid,String prefix) { try { if(getLock(uid, prefix)) { Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" getLock success"); } else { System.out.println(Thread.currentThread().getName()+" not getLock"); } } catch (Exception e) { e.printStackTrace(); } finally { removeLock(uid, prefix); } } public static boolean getLock(String uid,String prefix){ String key = uid + prefix; synchronized(key.intern()){ if(map.contains(key)){ return false; } else { System.out.println(Thread.currentThread().getName()+" getLocking..."); map.add(key); return true; } } } public static void removeLock(String uid,String prefix){ String key = uid + prefix; synchronized(key.intern()){ System.out.println(Thread.currentThread().getName()+" removeLocking..."); map.remove(key); } } public static void main(String[] args) { for(int i=0;i<20;i++) { new Thread() { @Override public void run() { testlock2("uid-a", "prefix_a"); //testlock("uid-a", "prefix_a"); } }.start(); } try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果,
Thread-0 getLocking... Thread-3 not getLock Thread-2 not getLock Thread-4 not getLock Thread-3 removeLocking... Thread-6 getLocking... Thread-7 not getLock Thread-7 removeLocking... Thread-8 getLocking... Thread-1 not getLock Thread-4 removeLocking... Thread-2 removeLocking... Thread-11 not getLock Thread-18 getLocking... Thread-15 not getLock Thread-15 removeLocking... Thread-16 getLocking... Thread-19 not getLock Thread-19 removeLocking... Thread-1 removeLocking... Thread-14 getLocking... Thread-10 not getLock Thread-10 removeLocking... Thread-12 getLocking... Thread-5 not getLock Thread-11 removeLocking... Thread-9 getLocking... Thread-5 removeLocking... Thread-13 getLocking... Thread-17 not getLock Thread-17 removeLocking... Thread-0 getLock success Thread-12 getLock success Thread-16 getLock success Thread-8 getLock success Thread-14 getLock success Thread-18 getLock success Thread-6 getLock success Thread-0 removeLocking... Thread-6 removeLocking... Thread-18 removeLocking... Thread-14 removeLocking... Thread-12 removeLocking... Thread-8 removeLocking... Thread-16 removeLocking... Thread-9 getLock success Thread-9 removeLocking... Thread-13 getLock success Thread-13 removeLocking...
根据结果,分析not getLock的线程也调用了removeLocking,所以这里不正确,修改为调用testlock方法,
结果如下,
Thread-0 getLocking... Thread-4 not getLock Thread-3 not getLock Thread-6 not getLock Thread-2 not getLock Thread-1 not getLock Thread-7 not getLock Thread-10 not getLock Thread-11 not getLock Thread-9 not getLock Thread-5 not getLock Thread-15 not getLock Thread-18 not getLock Thread-19 not getLock Thread-14 not getLock Thread-13 not getLock Thread-17 not getLock Thread-8 not getLock Thread-12 not getLock Thread-16 not getLock Thread-0 getLock success Thread-0 removeLocking...
结果正确,解决问题,
另外还可以使用ReentrantLock也可以实现同样的效果,代码如下,
import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.ReentrantLock; public class LockTest2 { static int size = 32; static List<ReentrantLock> locks = new ArrayList<ReentrantLock>(size); static { for(int i=0;i<size;i++) { locks.add(new ReentrantLock()); } } public static boolean getLock(String uid,String prefix){ String key = uid + prefix; ReentrantLock lock = locks.get(Math.abs(key.hashCode())%size); return lock.tryLock(); } public static void removeLock(String uid,String prefix){ String key = uid + prefix; ReentrantLock lock = locks.get(Math.abs(key.hashCode())%size); if(lock.isHeldByCurrentThread()) { lock.unlock(); } } public static void testlock(String uid,String prefix) { try { if(getLock(uid, prefix)) { Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" getLock success"); } else { System.out.println(Thread.currentThread().getName()+" not getLock"); } } catch (Exception e) { e.printStackTrace(); } finally { removeLock(uid, prefix); } } public static void main(String[] args) { for(int i=0;i<20;i++) { new Thread() { @Override public void run() { testlock("uid-a", "prefix_a"); } }.start(); } try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果如下,
Thread-2 not getLock Thread-4 not getLock Thread-0 not getLock Thread-3 not getLock Thread-6 not getLock Thread-5 not getLock Thread-7 not getLock Thread-8 not getLock Thread-10 not getLock Thread-11 not getLock Thread-9 not getLock Thread-12 not getLock Thread-14 not getLock Thread-15 not getLock Thread-16 not getLock Thread-13 not getLock Thread-17 not getLock Thread-18 not getLock Thread-19 not getLock Thread-1 getLock success
效果一样,其中
lock.isHeldByCurrentThread()代码就相当于方法一中的 flag=getLock(uid, prefix) ,if(flag)removeLock(uid, prefix); 这个判断