php中共享内存的奇怪行为

时间:2015-07-25 16:07:55

标签: php multithreading shared-memory

我正在以这种方式使用shmop和pcntl exts: 1.分叉几个线程 2.在所有分叉线程和主线程中使用相同的键打开共享内存段。 3.写入/读取段。 4.删除并创建具有更大尺寸的原始名称的段。

有时我的代码工作正常,所有线程都会更改值,以便其他线程可以使用这些值。但在大多数情况下,线程的工作方式就像“没有提供id的段”。虽然上述投诉清楚地表明其中一个线程已经创建了具有相同ID的段。

要发现该段尚未创建,我尝试用'w'标志打开它,如果它抱怨不存在的段,我用'c'标志创建它。

执行此操作的方法:

protected function open() {
    // probe
    echo '=== KEY IS: '.$this->key.PHP_EOL;
    $this->memory = shmop_open($this->key, 'w', 0, 0);
    if ($this->memory === false) {
        echo getmypid().'Create segment'.PHP_EOL;
        $this->memory = shmop_open($this->key, 'c', 0666, strlen(serialize($this->initialValue)));
    } else {
        echo getmypid().'Open segment'.PHP_EOL;
    }
}

我的输出在这里:

I am child: 6370
...
=== KEY IS: 1895898008
PHP Warning:  shmop_open(): unable to attach or create shared memory segment in /home/debian/MiniThreader/src/CommonStorage.php on line 90
...
I am child: 6369
...
I am child: 6368
...
6370Create segment
Expanding size from 6 to 17
New size is 17
...
=== KEY IS: 1895898008
6369Open segment
...
Expanding size from 17 to 28
...
=== KEY IS: 1895898008
6368Open segment
...
Expanding size from 28 to 39
New size is 39
...
I am child: 6367
...
=== KEY IS: 1895898008
PHP Warning:  shmop_open(): unable to attach or create shared memory segment in /home/debian/MiniThreader/src/CommonStorage.php on line 90
6367Create segment
...
Expanding size from 6 to 17
New size is 17
...
=== KEY IS: 1895898008
PHP Warning:  shmop_open(): unable to attach or create shared memory segment in /home/debian/MiniThreader/src/CommonStorage.php on line 90
6366Create segment
string(6) ""

在此代码中,所有线程都尝试将其进程标识符添加到数组中,并在需要时增加它。

  • 第一个帖子(6369)找不到共享段,因此会创建一个= right
  • 之后,第二个线程(6370)可以找到以前创建的段,因此它使用它= right
  • 之后,第三个线程(6368)执行相同的=
  • 但第四个帖子(6367)没有找到该段并创建一个新段。 = 错误
  • 毕竟主线程也找不到该段并再次创建它= 错误

所以,我的问题是:为什么有时线程无法正常使用共享段,以及这种行为在较低级别的性质是什么?

是的,我正在使用信号量来防止同时扩展:

protected function expand($newsize) {
    sem_acquire($this->sizeSemaphore);

    shmop_delete($this->memory);
    $this->memory = shmop_open($this->key, 'c', 0644, $newsize);

    sem_release($this->sizeSemaphore);
}

1 个答案:

答案 0 :(得分:0)

关于析构函数

这个问题与记忆无关。析构函数(__destruct)就是答案。

对于那些面临共享内存或其他任何问题的人,请考虑重写可以删除数据的析构函数。

在我的案例中,使用内存段的类在析构函数中有删除内存段的代码。但是这个动作只是在主线程中。