многопоточность — странное поведение разделяемой памяти в переполнении стека

Я использую shmop и pcntl exts таким образом:
1. Вилка несколько ниток
2. Откройте сегмент разделяемой памяти одним и тем же ключом во всех разветвленных нитях и в главном потоке.
3. Запись / чтение в / из сегмента.
4. Удалите и создайте сегмент с его оригинальным именем большего размера.

Иногда мой код работает правильно, и все потоки меняют значения, чтобы другие потоки могли использовать эти значения. Но в большинстве случаев потоки работают так: «нет сегмента с указанным идентификатором». Хотя вышеупомянутые жалобы ясно показывают, что в одном из потоков уже создан сегмент с таким же идентификатором.

Чтобы обнаружить, что этот сегмент еще не создан, я пытаюсь открыть его с флагом ‘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) не может найти общий сегмент, поэтому он создает один = право
  • После этого второй поток (6370) может найти ранее созданный сегмент, поэтому он использует его = право
  • После этого третий поток (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);
}

0

Решение

Речь идет о деструкторах

Этот вопрос не о памяти. Деструкторы (__destruct) является ответом.

Для тех, кто сталкивался с такими же проблемами с общей памятью или чем-то еще, рассмотрите возможность переписать ваши деструкторы, которые могут удалять данные, прежде чем вы действительно захотите это сделать.

В моем случае класс, который работает с сегментом памяти, имел код в деструкторе, который удаляет сегмент памяти. Но это действие предназначено только для основного потока.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]