• 动态生成Long类型数据不能作synchronized锁对象的解决方法(String中intern()方法的使用)


    在前期系统开发中,系统升级成了区域版本的,一个系统拥有多个机构,机构ID字段是字符串类型的,在java中由于字符串可以缓存在常量池中,之前都是用机构ID作为锁条件的,这样可以保证,同一个机构是串行的而不同机构是并行的。

    最近使用新框架,机构ID由String类型升级成了Long类型,这样再直接使用机构ID作synchronized的锁对象肯定是不行的,因为并没有常量池来缓存Long类型数据,不过跟Integer类型一样,Long类型自身也是做了缓存的:

    public static Long valueOf(long l) {
            final int offset = 128;
            if (l >= -128 && l <= 127) { // will cache
                return LongCache.cache[(int)l + offset];
            }
            return new Long(l);
        }
    

    可以看到缓存区域也是[-128,127],在这个区域内使用栈赋值的方式声明变量,可以保证引用地址是同一个,超过这个区域就不行了,我不能保证机构ID只在这个范围内啊,怎么解决呢?
    首先想到的就是把机构ID重新转成字符串,不就行了吗。
    Long.toString方法源码:

     public static String toString(long i) {
            if (i == Long.MIN_VALUE)
                return "-9223372036854775808";
            int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
            char[] buf = new char[size];
            getChars(i, size, buf);
            return new String(buf, true);
        }
    

    可以看到,他每次返回的都是一个new出来的字符串对象,这样锁对象就变了,是锁不住的。这个时候String的intern方法就出场了。

    在jdk1.6中,该方法把字符串的值复制到常量区,然后返回常量区里这个字符串的值;
    在jdk1.7里,该方法在常量区记录该字符串首次出现的实例引用,然后返回该地址,常量区可以保存字面量也可以保存字符串对象在堆中的引用。
    因为jdk7中intern方法是(在常量区找不到该字符串时)将该字符串对象在堆里的引用注册到常量区,以后使用相同字面量(双引号形式)声明的字符串对象都指向该地址,也就是该字符串在堆中的地址。用代码说明一下:

    public static void main(String[] args) {
            String str1 = new String("abc");
            String str2 = (new String("a") + new String("bc"));
            System.out.println(str1 == str2);// false
            System.out.println(str1.intern() == str2.intern());// true
        }
    

    上面的str1和str2地址肯定是不相同的,但是用于字面量是相同的所以,intern方法的返回值再比较就是相同的啦,这样问题就就解决了:

    Long jiGouId = Loginutils.currentDoneOrgId();
    String lockCondition = Long.toString(jiGouId).intern();
    synchronized (lockCondition) {
    	// dosomething
    }
    
    一颗安安静静的小韭菜。文中如果有什么错误,欢迎指出。
  • 相关阅读:
    nginx实现请求的负载均衡 + Keep Alive实现nginx的高可用
    理解什么是JWT(Json web token)及Python实现
    TCP/UDP协议到底是什么
    Redis实现分布式单点登录
    Python面试题---给定一个字符串 {xxx[xxx{xxx}]xx{x[xxx]xxx{xxx}xx}x} 判断其中的 {}[]() 是否成对出现
    Typora里面如何快捷改变字体颜色?
    基于Docker安装关系型数据库PostgrelSQL替代Mysql
    PEP8-Python编码规范
    欢迎来到我的友链小屋
    windows下lib和dll区别
  • 原文地址:https://www.cnblogs.com/c-Ajing/p/13448364.html
Copyright © 2020-2023  润新知