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); 这个判断
  • 相关阅读:
    laravel 验证码手机与提交手机的验证?
    微信公众平台开发——微信授权登录(OAuth2.0)
    个人网站可以申请微信授权登录吗
    个人网站可以申请微信授权登录吗?
    个体户微信公众号认证怎么做?无公章
    [微信开发] 没有组织机构代码证、公章怎么认证微信公众号?
    mysql中int、bigint、smallint 和 tinyint的区别详细介绍
    laravel5.6 QQ 第三方登录
    如何给网站的链接设置为绝对地址原文链接
    ArcGIS中文件共享锁定数据溢出 这个方法不行,建议用gdb,不要用mdb
  • 原文地址:https://www.cnblogs.com/xiongjinpeng/p/12911663.html
Copyright © 2011-2022 走看看