java 记一次synchronized的错误使用 LockUtil工具类
代码如下,
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); 这个判断
浙公网安备 33010602011771号