首页 > PHP专栏 > PHP解决并发问题的实现方法
2019
01-03

PHP解决并发问题的实现方法

对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了.在PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制。

方法一:使用文件锁排它锁

flock函数用于获取文件的锁,这个锁同时只能被一个线程获取到,其它没有获取到锁的线程要么阻塞,要么获取失败

在获取到锁的时候,先查询库存,如果库存大于0,则进行下订单操作,减库存,然后释放锁

flock()函数锁定或释放文件 若成功,则返回 true。若失败,则返回 false。

flock($fp,lock,block)

lock

共享锁定(读取) LOCK_SH

独占锁定(写入) LOCK_EX

释放锁定LOCK_UN

block 若设置为true 则当进行锁定时阻挡其他进程

注意

1.使用共享锁LOCK_SH,如果是读取,不需要等待,但如果是写入,需要等待读取完成。

2.使用独占锁LOCK_EX,无论写入/读取都需要等待。

3.LOCK_UN,无论使用共享/读占锁,使用完后需要解锁。

4.LOCK_NB,当被锁定时,不阻塞,而是提示锁定。

这里可用文件锁来解决:

阻塞(等待)模式

<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX))   //锁定当前指针,,,
{
  //..处理订单
  flock($fp,LOCK_UN);
}
fclose($fp);
?>

非阻塞模式

<?php
$fp = fopen("lock.txt", "w+");
if(flock($fp,LOCK_EX | LOCK_NB))
{
  //..处理订单
  flock($fp,LOCK_UN);
}
else
{
  echo "系统繁忙,请稍后再试";
}
 
fclose($fp);
?>

方法二:使用MySQL数据库提供的悲观锁

Innodb存储引擎支持行级锁,当某行数据被锁定时,其他进程不能对这行数据进行操作

先查询并锁定行:

select stock_num from table where id=1 for update
if(stock_num > 0){
    //下订单
    update table set stock_num=stock-1 where id=1
}


留下一个回复