需要使用锁的场景
满足多个线程共同操作同一共享文件的时候可能发生线程安全问题
目录
悲观锁 (Pessimistic Lock)
顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。
Java synchronized 就属于悲观锁的一种实现,每次线程要修改数据时都先获得锁,保证同一时刻只有一个线程能操作数据,其他线程则会被block。
排它锁/读锁:FOR UPDATE
只允许一个线程进行操作,多个线程同时操作时阻塞
共享锁/写锁:LOCK IN SHARE MODE
允许多个线程进行读取操作,但其他操作会阻塞
//悲观锁示例:更新库存
public boolean updateStock(Long productId){
//先锁定商品库存记录
ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId} FOR UPDATE", productId);
if (product.getNumber() < 0) {
int updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId}", productId);
if(updateCnt < 0){ //更新库存成功
return true;
}
}
return false;
}
乐观锁 (Optimistic Lock)
顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于读多写少的应用场景,这样可以提高吞吐量。
//乐观锁示例:更新库存 public boolean updateStock(Long productId){ int updateCnt = 0; while (updateCnt == 0) { ProductStock product = query("SELECT * FROM tb_product_stock WHERE product_id=#{productId}", productId); if (product.getNumber() > 0) { updateCnt = update("UPDATE tb_product_stock SET number=number-1 WHERE product_id=#{productId} AND number=#{number}", productId, product.getNumber()); if(updateCnt > 0){ //更新库存成功 return true; } } else { //卖完啦 return false; } } return false; }