所以我有一个主类调用另一个单例类,但是当运行多个线程(或并发线程)时,我会遇到交叉数据污染.这是一个非常简单的版本来解释这个问题.所有变量setter / getter都在Singleton中,由主类调用和设置.
class A {
public function doSomething($var) {
Singleton::instance()->setvar($var);
}
public function showSomething() {
return Singleton::instance()->getvar();
}
}
//单身人士
class Singleton {
private static $instance = null;
private $var;
public static function instance() {
if(!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
return self::$instance;
}
public function setvar($var) {
$this->var = $var;
}
public function getvar() {
return $this->var;
}
}
测试脚本1:
$actions = Array(
'one',
'two',
'three',
);
foreach($actions as $act) {
$action = new A();
$action->doSomething($act);
echo "Action: ".$action->showSomething()."\n";
sleep(2);
}
测试脚本1输出将有;
one
two
three
测试脚本2:
$actions = Array(
'1',
'2',
'3',
);
foreach($actions as $act) {
$action = new A();
$action->doSomething($act);
echo "Action: ".$action->showSomething()."\n";
sleep(2);
}
测试脚本2输出将有;
1
2
3
one
two
three
(不按此顺序,可能缺少其中一个值)
那么为什么在同时执行两个脚本时,测试2中包含测试1?
我是如何测试的:
打开两个终端,在每个终端执行一个脚本(因此睡眠),这样我就可以看到数据污染了.
解决方法:
您在问题中写道,test1和test2是两个独立的进程.从您给出的示例代码中我看不到两个脚本以允许进行跨进程交换的方式交换数据(而不是代码)(例如,通过文件,会话等).
但是从症状看起来,当你执行test2时,也会执行test1.
为了更好地理解正在发生的事情,您可以将代码添加到您的单例类中,以回显它当前所做的事情.例如.设置变量或显示它.然后,您可以跟踪问题发生的原因.您应该快速找出问题所在的根源.
或者,如果您手头有一个带调试器支持的IDE,您也可以通过逐步执行来执行此操作.
class Singleton {
private static $instance = null;
private $var;
public static function instance() {
if(!isset(self::$instance)) {
$c = __CLASS__;
self::$instance = new $c;
}
echo 'Singleton Instantiated.',"\n";
return self::$instance;
}
public function setvar($var) {
echo 'Singleton::setvar(', $var, ').',"\n";
$this->var = $var;
}
public function getvar() {
echo 'Singleton::getvar(): "', $var, '".',"\n";
return $this->var;
}
}