结构代码
public function index(){ $fp = fopen("lock.txt", "w+"); if(flock($fp,LOCK_EX)) { // 处理商品数据 flock($fp,LOCK_UN); } fclose($fp); }
概述:
1.首先,读写方式打开或者创建文件lock.txt文件
2.给lock.txt文件上 "独占锁",上锁成功后就可以进行下一步"处理订单商品数据了"
3.处理完数据后,要"释放锁”,以及fclose关闭打开的文件
注意:给文件“独占锁”后,如果再没有里面的“释放锁”,就没有下一个"轮回"
fopen详细介绍:http://www.w3school.com.cn/php/func_filesystem_fopen.asp
flock详细介绍:http://www.w3school.com.cn/php/func_filesystem_flock.asp
fclose详细介绍:http://www.w3school.com.cn/php/func_filesystem_fclose.asp
详细代码
namespace appindexcontroller; use thinkController; use thinkCache; class Index extends Controller { /** * 首页 * */ public function index(){ $fp = fopen("lock.txt", "w+"); if(flock($fp,LOCK_EX)) //锁定当前指针,,, { //..处理订单 $stock = $this->findStock(); if($stock > 0){ $this->setDec(); }else{ return '抢购失败'; } return $stock; flock($fp,LOCK_UN); } fclose($fp); } /** * 查询数据库库存 * */ public function findStock(){ $res = db('info')->where('id',1)->field('stock')->lock(true)->find(); return $res['stock']; } /** * 减少库存操作 * */ public function setDec(){ $res = db('info')->where('id',1)->setDec('stock',1); return $res; } }
总结有点:
1.可以解决并发问题,库存为负数的情况。
2.并发是,大家都在等待。当所有并发结束后,才会获得跳转(这也是缺点,如果处理1000条并发,需要时间15s,那么所有参加的人都需要等待15s后才进入下一个页面)
非阻塞模式
结构代码,与阻塞模式不同的地方 LOCK_NB (如果不希望 flock() 在锁定时堵塞,则给 lock 加上 LOCK_NB)
代码:
public function index(){ $fp = fopen("lock.txt", "w+"); if(flock($fp,LOCK_EX | LOCK_NB)) { $stock = $this->findStock(); if($stock > 0){ $this->setDec(); }else{ return '抢购失败'; } $this->setDec(); return $stock; flock($fp,LOCK_UN); } else { echo "抢购失败,要不再试试"; } fclose($fp); }
总结:
1.相比阻塞模式的时间等待,非阻塞模式则更加人性化很多
2.如果有有很多人都进入抢购,人太多就会直接进入第二个动作(“抢购失败界面”)。部分人就会进入第一个动作(“抢购候选名单”), 下一个步骤1.抢购成功 或者2 抢购失败