ホームページ  >  記事  >  バックエンド開発  >  PHP のシングルトン モードにおけるスレッド セーフティの問題についての考え

PHP のシングルトン モードにおけるスレッド セーフティの問題についての考え

WBOY
WBOYオリジナル
2023-10-15 10:14:01501ブラウズ

PHP のシングルトン モードにおけるスレッド セーフティの問題についての考え

PHP におけるシングルトン モードのスレッド セーフについて考える

PHP プログラミングでは、シングルトン モードは一般的に使用される設計パターンであり、クラスが存在することを保証できます。インスタンスは 1 つだけであり、このインスタンスにアクセスするためにグローバル アクセス ポイントが提供されます。ただし、マルチスレッド環境でシングルトン パターンを使用する場合は、スレッドの安全性の問題を考慮する必要があります。

シングルトン パターンの最も基本的な実装には、プライベート コンストラクター、プライベート静的変数、およびパブリック静的メソッドが含まれます。具体的なコードは次のとおりです。

class Singleton
{
    private static $instance;

    private function __construct()
    {
        // 保证外部无法通过new关键字创建实例
    }

    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

シングルスレッド環境では、上記のコードは非常にうまく機能します。 getInstance() メソッドが呼び出されるたびに、$instance が空かどうかがチェックされ、空の場合は新しいインスタンスが作成されます。それ以外の場合は、既存のインスタンスが直接返されます。

ただし、マルチスレッド環境では、同時アクセスの問題が発生します。複数のスレッドが getInstance() メソッドを同時に呼び出すと、$instance が空であることを同時に確認し、複数のインスタンスを同時に作成することがあります。これはシングルトン パターンの目的に反します。

スレッド セーフの問題を解決するには、ロックを使用して、1 つのスレッドのみがインスタンスを作成できるようにします。具体的なコードは次のとおりです。

class Singleton
{
    private static $instance;

    private function __construct()
    {
        // 保证外部无法通过new关键字创建实例
    }

    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            // 加锁
            synchronized(self::$instance) {
                if (!isset(self::$instance)) {
                    self::$instance = new self();
                }
            }
        }
        return self::$instance;
    }
}

上記のコードでは、ロックする必要があるコード ブロックをラップするために synchronized キーワードを導入しました。こうすることで、1 つのスレッドがこのコード ブロックに入ると、他のスレッドが待機します。

ロックによってスレッドの安全性は確保されますが、パフォーマンスの低下ももたらします。 getInstance() メソッドが呼び出されるたびにロックとロック解除の操作が必要になるため、プログラムのオーバーヘッドが増加します。

もう 1 つの方法は、PHP の atomic ライブラリを使用して、アトミック操作を通じてスレッドセーフ シングルトン モードを実装することです。具体的なコードは次のとおりです。

class Singleton
{
    private static $instance;

    private function __construct()
    {
        // 保证外部无法通过new关键字创建实例
    }

    public static function getInstance()
    {
        $closure = function () {
            self::$instance = new self();
        };

        $atomic = new SwooleAtomic();

        if (!isset(self::$instance)) {
            if ($atomic->cmpset(0, 1)) {
                $closure();
                $atomic->set(0);
            } else {
                while (!isset(self::$instance)) {
                    // 占位,避免空循环
                }
            }
        }
        return self::$instance;
    }
}

上記のコードでは、PHP の swoole ライブラリを使用し、アトミック操作を使用してスレッド セーフを実現します。 swooleAtomic クラスを使用してアトミック変数を作成します。アトミック変数が 0 の場合は、cmpset メソッドを使用してアトミック変数を 1 に設定し、 an instance; create インスタンスが完了したら、アトミック変数を 0 にリセットします。他のスレッドがコード ブロックに入ると、$instance が空でなくなるまでループで待機し続けます。

すべての PHP 環境が swoole ライブラリをサポートしているわけではないため、使用する前に PHP 環境がサポートしているかどうかを確認する必要があることに注意してください。

要約すると、PHP でシングルトン モードを使用する場合は、スレッド セーフの問題を考慮する必要があります。ロック操作またはアトミック操作により、1 つのスレッドのみがインスタンスを作成できるようになりますが、これによりパフォーマンスも低下します。実際の状況に応じて適切な方法を選択し、スレッドの安全性を確保しながらプログラムのパフォーマンスを向上させます。

以上がPHP のシングルトン モードにおけるスレッド セーフティの問題についての考えの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。