Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Pemikiran tentang isu keselamatan benang dalam mod tunggal dalam PHP

Pemikiran tentang isu keselamatan benang dalam mod tunggal dalam PHP

WBOY
WBOYasal
2023-10-15 10:14:01501semak imbas

Pemikiran tentang isu keselamatan benang dalam mod tunggal dalam PHP

Memikirkan isu keselamatan benang mod tunggal dalam PHP

Dalam pengaturcaraan PHP, mod tunggal ialah corak reka bentuk yang biasa digunakan, yang memastikan bahawa kelas hanya mempunyai satu tika dan menyediakan pusat akses global untuk mengakses tika ini. Walau bagaimanapun, apabila menggunakan corak tunggal dalam persekitaran berbilang benang, isu keselamatan benang perlu dipertimbangkan.

Pelaksanaan paling asas bagi corak tunggal termasuk pembina persendirian, pembolehubah statik persendirian dan kaedah statik awam. Kod khusus adalah seperti berikut:

class Singleton
{
    private static $instance;

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

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

Dalam persekitaran satu benang, kod di atas berfungsi dengan baik. Setiap kali kaedah getInstance() dipanggil, ia akan menyemak sama ada $instance kosong dan mencipta tika baharu jika ia kosong. Jika tidak, contoh sedia ada dikembalikan secara langsung. getInstance()方法时,都会检查$instance是否为空,如果为空则创建一个新的实例。否则,直接返回已有的实例。

然而,在多线程环境下,存在并发访问的问题。当多个线程同时调用getInstance()方法时,可能会同时检查到$instance为空,然后同时创建多个实例。这违背了单例模式的初衷。

为了解决线程安全性的问题,我们可以通过加锁来确保只有一个线程能够创建实例。具体代码如下:

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关键字,将需要加锁的代码块包裹起来。这样,当一个线程进入这个代码块时,其他线程将等待。

尽管通过加锁确保了线程安全性,但也带来了性能的降低。因为每次调用getInstance()方法时都需要进行加锁和解锁操作,这会增加程序的开销。

另一种方式是利用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,然后创建实例;创建完实例后将原子变量重新设置为0。其他线程在进入代码块时,会不断循环等待$instance不为空。

需要注意的是,并非所有的PHP环境都支持swoole

Namun, dalam persekitaran berbilang benang, terdapat masalah akses serentak. Apabila berbilang urutan memanggil kaedah getInstance() pada masa yang sama, mereka boleh menyemak bahawa $instance kosong pada masa yang sama, dan kemudian mencipta berbilang kejadian pada masa yang sama . Ini mengalahkan tujuan corak tunggal.

Untuk menyelesaikan masalah keselamatan benang, kami boleh menggunakan penguncian untuk memastikan hanya satu utas boleh mencipta contoh. Kod khusus adalah seperti berikut: #🎜🎜#rrreee#🎜🎜#Dalam kod di atas, kami memperkenalkan kata kunci disegerakkan untuk membalut blok kod yang perlu dikunci. Dengan cara ini, apabila satu utas memasuki blok kod ini, utas lain akan menunggu. #🎜🎜##🎜🎜#Walaupun keselamatan benang dipastikan melalui penguncian, ia juga membawa pengurangan prestasi. Oleh kerana operasi mengunci dan membuka kunci diperlukan setiap kali kaedah getInstance() dipanggil, ini akan meningkatkan overhed program. #🎜🎜##🎜🎜#Cara lain ialah menggunakan pustaka atomic PHP untuk melaksanakan mod singleton selamat benang melalui operasi atom. Kod khusus adalah seperti berikut: #🎜🎜#rrreee#🎜🎜#Dalam kod di atas, kami menggunakan pustaka swole PHP dan menggunakan operasi atom untuk mencapai keselamatan benang. Cipta pembolehubah atom melalui kelas Atomic swoole Apabila pembolehubah atom ialah 0, tetapkan pembolehubah atom kepada 1 melalui kaedah cmpset, dan kemudian buat Instance; tetapkan semula pembolehubah atom kepada 0 selepas mencipta contoh. Apabila urutan lain memasuki blok kod, mereka akan terus menunggu dalam gelung sehingga $instance tidak kosong. #🎜🎜##🎜🎜#Perlu diingatkan bahawa tidak semua persekitaran PHP menyokong pustaka swole, jadi anda perlu mengesahkan sama ada persekitaran PHP boleh menyokongnya sebelum menggunakannya. #🎜🎜##🎜🎜#Ringkasnya, apabila menggunakan mod tunggal dalam PHP, anda perlu mempertimbangkan isu keselamatan benang. Operasi penguncian atau atom boleh memastikan bahawa hanya satu utas boleh mencipta contoh, tetapi ini juga mengurangkan prestasi. Pilih kaedah yang sesuai mengikut situasi sebenar untuk meningkatkan prestasi program sambil memastikan keselamatan benang. #🎜🎜#

Atas ialah kandungan terperinci Pemikiran tentang isu keselamatan benang dalam mod tunggal dalam PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn