Проблема переменной области класса, перекрестное загрязнение данных - PullRequest
3 голосов
/ 08 июня 2011

Итак, у меня есть основной класс, который вызывает другой одноэлементный класс, но при запуске нескольких потоков (или параллельных потоков) я получаю перекрестное загрязнение данных.Это очень простая версия, чтобы объяснить проблему.Все установщики / получатели переменных находятся в Singleton и вызываются и устанавливаются основным классом.

class A {

    public function doSomething($var) {
        Singleton::instance()->setVar($var);
    }

    public function showSomething() {
        return Singleton::instance()->getVar();
    }

}

// Singleton

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

(не в этом порядке, и в нем может отсутствовать одно из значений)

Так почему тест 1 включен в результаты теста 2 при выполнении обоих сценариев одновременно?

Как я тестирую:

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

Ответы [ 2 ]

3 голосов
/ 08 июня 2011

Вы пишете в своем вопросе, что test1 и test2 - это два отдельных процесса.Из приведенного вами примера кода я не вижу, чтобы оба сценария обменивались данными (а не кодом) таким образом, чтобы можно было осуществлять обмен между процессами (например, через файл, сеанс и т. Д.).

Однако из симптомовпохоже, что когда вы выполняете test2, также выполняется test1.

Чтобы лучше понять, что происходит, вы можете добавить в свой класс singleton код, который повторяет то, что он в данный момент делает.Например, установка переменной или ее показ.Тогда вы можете проследить, почему ваша проблема возникает.Вы должны довольно быстро выяснить, в чем причина проблемы.

В качестве альтернативы, если у вас есть 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;
    }
}
2 голосов
/ 08 июня 2011

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

Даже при наличии сотен значений в каждом экземпляре script1 и script2, ни разу, когда script1 и script2 работали в непрерывных циклах, они не перезаписывали одноэлементные свойства друг друга.

Пробовал и повторял в течение 10 минут,просто чтобы быть полностью уверенным.

OP либо делает свой тест неверно, либо обнаружен недостающий фрагмент головоломки.

Тем не менее, синглтоны не распределяются между процессами .Как и ожидалось, конечно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...