-
单机部署的应用
一、可以使用jvm本地锁,比如synchronized来同步代码块或者@Synchronized来将整个方法变为同步方法,或者使用ReentrantLock lock() unlock() 锁定代码。
jvm本地锁失效的三种情况:
1、被锁定(或者说被同步)的代码块所在方法如果是多例模式或者此方法所在控制器是多例模式:因为多例模式下多个线程不会公用一个控制器,用的不是同一个资源,jvm锁就会失效。
2、集群部署,很明显不是同一个进程,甚至不是同一台服务器,jvm本地锁自然失效,本地锁只能对统一进程内的多个线程起到锁定同步作用。
3、被锁定方法或者代码块外层使用事务,且被锁定代码包含查询和查询,且查询的SQL没有使用悲观锁。比如第一个线程释放锁后还未提交事务,第二个线程获得锁,执行查询,查询到第一个线程操作前的数据,继续往下执行。它应该查询到第一个线程提交后的数据,这样才起到线程在执行这段代码时序列化的作用。
二、也可以使用MySQL的锁:
1、用一条SQL完成更新。比如:update stock set count = count - 1 where id = ‘xxx’。MySQL默认每条更新数据库的操作都会自动加上事务。
2、用悲观锁,先用select…for update 查询,在更新。注意这里两个对数据库的操作一个查询,一个更新。要放在一个事务中进行才能使用到select…for update的悲观锁。方法上要加上@Transactional。
3、用乐观锁,乐观锁就是在数据库表上添加一个version字段,每次更新都对这个字段+1,每次更新前先读出version的值,更新时将version也一并作为更新条件,如果不成功再执行上面的查询更新,直到成功为止。并发写数据库很多的情况下,乐观锁要不断地重试才能成功,吞吐量反而不如悲观锁。 -
集群部署的应用
分布式应用环境中MySQL的锁也能起到锁定数据的作用,也能当作分布式锁使用。所以如果是集群部署,也可以使用MySQL的锁