同时触发两个AJAX请求时第二个被阻塞直到第一个执行完成如何解决?
问题原因
这是PHP会话独占锁导致的阻塞问题:
PHP默认基于文件的会话实现会在调用session_start()后给会话文件加独占锁,同一个客户端的同会话请求,只要前一个请求没有释放会话锁,后续所有调用了session_start()的请求都会被挂起等待锁释放,直到前一个请求执行结束自动释放锁。你的代码里b.php全程持有会话锁,所以c.php的session_start()会一直阻塞到b.php执行完毕才能继续运行。
解决方法
核心方案:修改b.php,每次更新会话进度后立即释放锁
使用session_write_close()函数可以主动将会话数据写入存储并释放独占锁,后续如果需要再次修改会话,重新调用session_start()即可,修改后的b.php代码如下:
<?php // 第一次更新进度 session_start(); sleep(2); $_SESSION["progress"] = 1; session_write_close(); // 写完立即释放锁 // 第二次更新进度 session_start(); sleep(2); $_SESSION["progress"] += 1; session_write_close(); // 第三次更新进度 session_start(); sleep(2); $_SESSION["progress"] += 1; session_write_close(); // 后续不需要操作会话的逻辑不需要再持有锁 sleep(2); ?>
可选优化:调整c.php为只读会话减少锁占用
PHP7及以上版本可以给session_start()添加read_and_close参数,读取完会话内容后立即释放锁,不需要等到请求结束,同时补充默认值避免会话未初始化时报错:
<?php session_start(['read_and_close' => true]); echo json_encode($_SESSION['progress'] ?? 0); ?>
内容的提问来源于stack exchange,提问作者DS9
相关产品推荐
相关产品推荐

