zoukankan      html  css  js  c++  java
  • 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); 这个判断
  • 相关阅读:
    查看自己的笔记本是否支持64位系统
    关闭445端口
    与postgis相关的一些常用的sql
    postgis 赋予postgresql空间数据库的能力
    ThreadLocal
    获取跨域请求的自定义的response headers
    java Bean的映射工具
    Java多线程学习
    (14)Spring Boot定时任务的使用【从零开始学Spring Boot】
    (13)处理静态资源(自定义资源映射)【从零开始学Spring Boot】
  • 原文地址:https://www.cnblogs.com/xiongjinpeng/p/12911663.html
Copyright © 2011-2022 走看看