我正在尝试在所有线程之间建立某种共享类。但是,我不确定如何使它可靠。
这是我的示例测试代码。基本上,它创建100个线程,为它们分配唯一的ID,将它们的引用传递给共享类实例并启动它们。在每个线程的run方法开始时,共享实例的共享计数器增加,并且线程的ID附加到共享数组。在run方法结束时,将减少计数器,并从数组中删除id元素。每个线程重复10次,以使其更可能导致错误。
在所有线程结束之后,预期结果是$ iCount = 0和空数组$ aArr。对于数组,这是可靠的方法,但对于$ iCount变量而言则不是。
class Shared extends \Threaded{
private $aArr = [];
private $iCount = 0;
public function add($s){
$this->iCount++;
$this->aArr[] = $s;
}
public function remove($s){
$this->iCount--;
foreach($this->aArr as $iKey => $iId){
if($iId == $s){
unset($this->aArr[$iKey]);
}
}
}
public function dump(){
var_dump('$this->iCount: ' . $this->iCount);
var_dump('sizeof($this->aArr): ' . sizeof($this->aArr));
}
}
class someThread extends \Thread{
private $Shared;
private $iId;
public function __construct($iId)
{
$this->iId = $iId;
}
public function setShared( $shared): void
{
$this->Shared = $shared;
}
public function run()
{
for($x = 0;$x < 10;$x++){
$this->Shared->add($this->iId);
usleep(rand(400000,500000));
$this->Shared->remove($this->iId);
}
}
}
$shared = new Shared();
$threads = [];
for($x = 0;$x < 100;$x++){
$thread = new someThread($x);
$thread->setShared($shared);
$thread->start();
$threads[] = $thread;
}
foreach($threads as $t){
$t->join();
}
$shared->dump();
多次执行此代码的结果是:
Execution 1:
string(17) "$this->iCount: 21"
string(22) "sizeof($this->aArr): 0"
Execution 2:
string(17) "$this->iCount: 14"
string(22) "sizeof($this->aArr): 0"
Execution 3:
string(16) "$this->iCount: 9"
string(22) "sizeof($this->aArr): 0"
因此,看起来原始int“ $ iCount”不是线程安全的,而数组“ $ aArr”是线程安全的。为什么?以及如何使跨线程的安全整数(作为类实例的成员)计数?