项目中难免会有需要锁的地方,尤其是库存的操作,更是需要保证数据正确。
过程:1.上锁 2.操作数据库 3.解锁
整个过程非常简单,就是在操作前创建一个文件,当其他线程操作前也会创建文件,但是文件已经存在,无法创建成功,那么文件就是一把锁,只有文件被删除(解锁)才可以操作。
代码如下:
https://download.csdn.net/download/xiaobai1024/13199884
调用文件锁的地方在操作之前,事务开启之后,当上锁成功后,事务结束后调用解锁,发生异常也代表操作失败,也要解锁。当然一次上锁不成功,可以循环上锁,超时放弃。
循环上锁代码:
//文件锁
lockresult2 = FileLockUtils.onLockPublicFile(rhp.getProductClassPath(), warehouse, "2");
if (!lockresult) {
int i = 0;
while (true) {
i = i + 200;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
lockresult = FileLockUtils.onLockPublicFile(rhp.getProductClassPath(), warehouse, "2");
if ((lockresult) || i >= 30000) {
break;
}
}
}
if (!lockresult) {
throw new RuntimeException("lock");
}
上锁失败后每隔200毫秒(把cup时间片让出来,不要自己独占30秒,会让其他线程卡死的)重新上锁。直到成功或超时再退出。
优缺点:
1.简单粗暴,上锁的范围通过文件名控制,可大可小,代码直接插入业务中,简单。
2.真正的排他,即使是分布式项目,多个服务器,固定文件的位置做共享文件,多个服务器的线程也可以互锁。
3.如果上锁后程序崩溃(重启)或者线程挂起则文件锁无法删除,会影响其他线程操作。
4.如果上锁颗粒度很小,则需要创建大量文件,删除时也需要删除大量文件,就不好操作了,还占用磁盘。
但是这个排他锁在项目中使用了很多年,说明还是可靠,虽然偶尔会造成卡死,但是上锁的颗粒度很大,直接锁一个库,或者一个订单,文件少,直接手动删除文件就可以了。