結構代碼
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 app\index\controller; use think\Controller; use think\Cache; 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 搶購失敗
