Java线程锁_模拟失效时修改值

来源:互联网 发布:windows git 配置文件 编辑:程序博客网 时间:2024/06/05 04:48

在开发过程中碰到的一个bug。我有个静态Map用来存储微信的普通access_token,其它接口获取access_token时,会判断access_token是否过期,过期则会调用获取access_token的接口,重新获取access_token,并覆盖Map中的值。

但这里存在并发的情况:在access_token失效时,多个请求同时获取access_token时,就会发生错误,只有最后一次获取的access_token才是可用的,但此时Map里存的却不一定是最后一次获取的access_token。

下面是我模拟过期时,修改值。

静态值

public class StaticProject {public static int count = 0; // 数public static long time = 1505227456849l; // 时间}

失效时调用的方法

public class ChangeValue {public void set(int a) {// 第一层判断if (StaticProject.time < System.currentTimeMillis()) {System.out.println("a = " + a + ", 第1层if, " + StaticProject.count);synchronized(ChangeValue.class) {// 第2层判断if (StaticProject.time < System.currentTimeMillis()) {StaticProject.count = a;StaticProject.time = System.currentTimeMillis() + 7200000;System.out.println("a = " + a + ", 第2层if, " + StaticProject.count);}}System.out.println("a = " + a + ", 第3层, " + StaticProject.count);}}}


线程1

public class Thread1 extends Thread {@Overridepublic void run() {ChangeValue cv = new ChangeValue();cv.set(10);System.out.println("Thread1 = " + StaticProject.count);}}


线程2

public class Thread2 extends Thread {@Overridepublic void run() {ChangeValue cv = new ChangeValue();cv.set(12);System.out.println("Thread2 = " + StaticProject.count);}}


测试

public static void main(String[] args) {Thread1 t1 = new Thread1();Thread2 t2 = new Thread2();t1.start();t2.start();System.out.println("main " + StaticProject.count);}

测试结果1

main 0a = 12, 第1层if, 0a = 10, 第1层if, 0a = 12, 第2层if, 12a = 12, 第3层, 12Thread2 = 12a = 10, 第3层, 12Thread1 = 12

从打印的数据可以看出thread1和thread2调用ChangeValue.set(a)。

均发现时间过期,准备修改时间值。

但thread2先拿到锁,thread2操作后,释放锁。

此时thread1再拿到锁,发现时间已经被修改了,是未过期的时间,则跳过修改。

上面的方案是基于原先的代码,在原先的代码上进行修改的,代码改动量少,但个人觉得不是这个不是好的解决方案。

还有另外的解决方案:专门开启一条线程,用来监视access_token的过期时间,若过期,则重新获取access_token。

这样其它接口可以直接获取access_token,而不用考虑access_token过期的问题。

但这个方案同样有个问题,就是其它接口获取access_token后,同时该监视线程重新获取了access_token,

会导致之前接口获取的access_token失效。


----------上面是个人见解,本人经验有限,如果有不对的地方或者有更好的解决方案,请多多批评指正,谢谢!--------


原创粉丝点击