背景:给智能柜加上锁,保证多个用户同时存物的时候,不会出现多个人打开同一个智能柜门的情况
synchorized介绍:synchorized包含两个部分,一个是锁,一个是被锁的内容
当多个线程到达synchorized时,会判断他的锁,如果该锁正在使用中,那么他就要等待使用的人用完了才可以用该锁进去,没被使用的话则可以直接访问。
PS:使用锁需要注意的是锁不能有多个。即锁之间要全等。例如A、B同时访问锁内容,需要保证锁一样才会排队。例如A的锁是字符串“a”,B的锁也是字符串“a”,如果“a”=="a",那么就会排队,如果两个“a”是两个对象则不会排队
锁的几种用法,
锁的位置 | 锁 | 锁的内容 | 例子 |
普通方法上 | 类实例对象 | 该普通方法 | |
静态方法上 | 类本身 | 该静态方法 | public static synchronized String getLocker(Long smartarkId){ |
代码块上 | 括号内的内容 | 大括号内的内容 | |
当synchorized加在方法上面,那么锁就是该实例对象(new了多少个对象就有多少个锁),如果两个线程的实例对象一致的话,那没就会排队
当synchorized加在静态方法上,那么锁就是该类本身(一把锁),不论实例有多少个,都会排队。
当synchorized加在对象上,那么锁就是该对象(小括号内的内容)。如果小括号里面的是类,就是类锁,全局一个(this.getClass或者LockerPool.class,this.getClass获取当前类,类名.class获取指定类)。如果小括号里面的是实例对象,那就是实例锁,(this)
正确示范:
示范一:
第一步,设置锁
第二步,需要加锁的内容加上锁
如上所示,使用的类本身作为锁,保证获取smartarkMap为同一个,再用smartarkMap作为锁保证每个智能柜打开的时候都会排队依次打开
运行结果
示范二:
第一步设置锁
需要加锁的内容上锁
下图是锁的实现,使用的单例模式下的类实例对象
如上所示,我设置了锁池smartarkMap记录全部的锁,同时为了防止LockerPool出现多个,我设置了单例。为了防止用户获取锁的时候出现同步,我在获取锁的方法上也加了锁(这个锁是LockerPool,锁的内容就是getLocker方法)
使用jmeter进行测试,同时调用7次该接口
可以看出,当第一个线程结束时已经有3个进程进来了,但是他们都等到第一个进程进去以后才开始开箱,数据库也保证了每个箱子都没有重复打开。该测试重复了20次,每次都是同时调用7次接口,未出现重复情况
PS:本来打算计划写错误方法的,写了一种后,想想错误的还是不要写详细了,说说吧。刚开始synchorized我是加在serviceimpl里面的,多次运行时有概率出错,加在controller后未出现该情况(或许是serviceimpl运行结束了但是还未存放到数据库?)synchorized后面的获取实例方法未加锁,导致运行时出现同时调用该方法,同时进去锁的内容里面的情况