基于php语言使用加锁实现并发情况下抢码功能,特定时间段开放抢码并不允许开放的码重复:

需求:抢码功能

要求:

1、特定时间段才开放抢码;

2、每个时间段放开的码是有限的;

3、每个码不允许重复;

实现:

1、在不考虑并发的情况下实现:

function get_code($len){

$CHAR_ARR = array('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','X','Y','Z','W','S','R','T');

$CHAR_ARR_LEN = count($CHAR_ARR) - 1;

$code = '';

while(--$len > 0){

$code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)];

}

return $code;

}

$pdo = new PDO('mysql:host=localhost;dbname=ci_test','root','root');

//查询当前时间已发放验证码数量

$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");

$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);

$code_num = $code_num_arr['sum'];

if($code_num < 1){

sleep(2); //暂停2秒

$code= get_code(6);

var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES ('$code',".time().")") );

}

上述代码默认满足当前是开放时间,和码是不重复的;

在不考虑并发情况下流程:

1)选查询当前数据库发放的验证码数量;

2)如果还有名额,则生成验证码,插入到数据库,返回验证码到客户端;

3)如果已满;则返回提示,已无名额;

2、并发情况下实现:

那么看下上面代码在并发情况下得到的结果:

测试并发,可以使用apache benchmark来测试,apache benchmark是APACHE旗下的HTTP SERVER的性能评测工具,通过cmd进入到apche的bin目录下,通过ab命令调用,如:ab -c 并发数量 -n 总访问量 url。

这样就是100个用户同事去抢1个名额,在查询的时候,每个用户都查询到还有一个名额,则会去生成验证码,插入数据库,返回验证码;这样就造成了验证码发多了。事实上,运行完该命令,数据库多了13条记录,而不是一条。

怎么避免这情况发生呢?

可以通过加排他锁来锁定判断到插入这个过程,保证这个判断流程任意一时间只有一个进程在运行。

实现如下:

//生成码

function get_code($len){

$CHAR_ARR = array('1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','X','Y','Z','W','S','R','T');

$CHAR_ARR_LEN = count($CHAR_ARR) - 1;

$code = '';

while(--$len > 0){

$code .= $CHAR_ARR[rand(0,$CHAR_ARR_LEN)];

}

return $code;

}

$pdo = new PDO('mysql:host=localhost;dbname=ci_test','root','root');

$fp = fopen('lock.txt','r');

//通过排他锁 锁定该过程

if(flock($fp,LOCK_EX)){

//查询当前时间已发放验证码数量

$code_num_rs = $pdo->query("SELECT COUNT(*) as sum FROM code_test");

$code_num_arr = $code_num_rs->fetch(PDO::FETCH_ASSOC);

$code_num = $code_num_arr['sum'];

if($code_num < 1){

sleep(2);

$code= get_code(6);

var_dump( $pdo->query("INSERT INTO code_test (code,create_time) VALUES ('$code',".time().")") );

}

flock($fp,LOCK_UN);

fclose($fp);

}

php通过标识加锁,PHP通过加锁实现并发情况下抢码功能相关推荐

  1. mysql不同情况下加锁类型实验 record lock 和 gap lock

    首先确定RR级别下mysql的加锁规则(实验环境 mysql 8.0): 加锁的基本单位是 next-key lock.是一个前闭后开的区间,也是record lock 和 gap lock 的组合. ...

  2. 【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)

    来自:冰河技术 声明 特此声明:文中有关支付宝账户的说明,只是用来举例,实际支付宝账户要比文中描述的复杂的多.也与文中描述的完全不同. 前言 很多网友留言说:在编写多线程并发程序时,我明明对共享资源加 ...

  3. shiro如何保证session不失效_请问在不加锁的情况下如何保证线程安全?

    概念 compare and swap,解决多线程并行情况下使用锁造成性能损耗的一种机制,CAS操作包含三个操作数--内存位置(V).预期原值(A)和新值(B).如果内存位置的值与预期原值相匹配,那么 ...

  4. c++客户端发送加锁_MySQL语句加锁分析详解

    前言 建立一个存储三国英雄的hero表: CREATE TABLE hero ( number INT, name VARCHAR(100), country varchar(100), PRIMAR ...

  5. POSIX 线程具体解释(3-相互排斥量:固定加锁层次/“试加锁-回退”)

    有时一个相互排斥量是不够的: 比方: 当多个线程同一时候訪问一个队列结构时,你须要2个相互排斥量,一个用来保护队列头,一个用来保护队列元素内的数据. 当为多线程建立一个树结构时.你可能须要为每一个节点 ...

  6. 在高并发分布式情况下生成唯一标识id

    做项目的时候经常会用id作为唯一标识. 但是当有这样一个需求出现的时候:工程分布式部署,要求抗住高并发.并且生成的id是根据时间自增的.解决这个问题有很多种方法,但是要选择一个性价比比较高的策略比较不 ...

  7. Python中字符串使用单引号、双引号标识和三引号标识,什么是三引号?什么情况下用哪种标识?

    一.三引号是指三个单引号或者三个双引号: 二.Python中字符串如果以单引号.双引号标识和三引号标识开头,则字符串结尾也必须是对应的标识,不能变更: 三.三者的异同: 1.三者都是字符串,大部分情况 ...

  8. mysql innodb 读加锁,Mysql InnoDB加锁分析

    在文章的开始,简单思考一个小问题:假如有一个SQL语句delete from T where id = 1,这条SQL在InnoDB中执行的时候数据库如何加锁的? 数据库的锁 要回答上面的问题,首先我 ...

  9. 【高并发】高并发场景下如何优化加锁方式?看完这篇我确实明白了!!

    来自:冰河技术 写在前面 很多时候,我们在并发编程中,涉及到加锁操作时,对代码块的加锁操作真的合理吗?还有没有需要优化的地方呢? 前言 在<[高并发]优化加锁方式时竟然死锁了!!>一文中, ...

最新文章

  1. 资源 | 麻省理工学院开放 2018 自动驾驶课程
  2. java分析日志文件_java程序如何对监控软件的日志文件进行如下分析?
  3. python 只取数值_Python:你会生成列表吗?-- 列表生成式
  4. SAP Spartacus产品转盘页面(ProductCarousel)的产品数据批量加载实现细节
  5. C语言 指针数组-字符指针数组整型指针数组 char*s[3] int*a[5] 数组指针int(*p)[4]
  6. 什么是Servlet类
  7. java readpassword_Java Password.readPassword方法代碼示例
  8. asp.net 与donet(.net)的区别
  9. TangIDE游戏开发之70行代码实现打地鼠
  10. RHEL Linux 8.3 通过 BIND 实现 DNS 基本功能
  11. 南昌人武学院计算机室,【志愿者日记】南昌大学人武学院:用行动感染身边的人...
  12. python-turtle(海龟绘图)圣诞树
  13. the info.plist in the package must contain the CFBundleShortVersionString key.
  14. 七牛云测试域名过期了,全部图片下载方法
  15. 千层套路“千层饼”,论面试中的套路与反套路
  16. Trying to access array offset on value of type null
  17. 克莱因瓶四维空间猜想
  18. 用word2013发布csdn博客
  19. 读《洛克菲勒给儿子的38封信》有感
  20. Introduction to JavaScript(JavaScript简介)

热门文章

  1. Elasticsearch修改字段之别名,扩展数据迁移
  2. linux 升级centos7,Linux之从Centos 6.x 升级Centos7
  3. java单线程上锁_关于Java多线程编程锁优化的深入学习
  4. python 找质数的个数_用Python打造一款文件搜索工具,所有功能自己定义!
  5. docker 删除image_如何用两个小时入门 Docker?
  6. python三种变量方式_python2.x 3种变量形式调用
  7. js读写php文件,在js中如何读取本地文件
  8. mysql永远不用utf8_永远不要在 MySQL 中使用「utf8」
  9. 腾讯视频如何删除观看记录
  10. 搜狐视频开放平台的申请使用方法