The design of coroutine in Open Swoole is similar to the coroutine in Golang:
The coroutine scheduler in Golang is multiple threads design. There are multiple coroutines parallel running, it is necessary to solve race conditions for the globally shared resources, to do synchronization and lock
the critical section`, please see more at: https://golang.org/pkg/sync/.
Although Golang has solved the problem of synchronizing between units of work by communicating over shared channels. But Golang still used mutex and locks underlayer.
The coroutine scheduler in Open Swoole 4.x is single thread design. Only one coroutine is parallel running, so there are no problems such as data syncing between threads and avoid locking
.
But how to share global variables and resources between different Swoole processes? There are three ways to solve this problem:
Swoole Table
or Swoole Atomic
or share memory structureIPC
, communicate between processesdefer
in Golang is binding with a function. The deferred task will be executed when the function is finished. This is used to clean up and release the resources created and used within the function.
For example, in Golang:
func test() {
db := new(database)
close := db.connect()
defer close()
fmt.Println("query db...")
}
defer task is needed to release the connection resources. Compare with the PHP style doing the defer task within destructor function
.
defer is doing similar tasks in Golang as a destructor in PHP.
Looking at this piece of normal PHP code:
<?php
function test() {
$db = new Database;
$db->connect('127.0.0.1', 6379);
$db->query($sql);
}
Compare with the Golang test function, it is not necessary to close the DB connection in PHP since PHP destroy and clean up the DB object created within the function. Because of the destructor function including the logic of closing the connection in Database
will be called before the DB object is destroyed.
defer in Swoole 4.x is designed to be executed when the coroutine
task is finished. It is binding with the coroutine task.
In Golang, it is possible to read the same socket with multiple coroutines concurrently. But the developer needs to control when to do so. For example, the following Golang code may throw errors:
func test() {
db := new(database)
close := db.connect()
go func(db) {
db.query(sql);
} (db);
go func(db) {
db.query(sql);
} (db);
}
Compare with Golang, reading socket concurrently with multiple coroutines is prohibited.
<?php
function test() {
$db = new Database;
$db->connect('127.0.0.1', 6379);
go(function () use ($db) {
$db->query($sql);
});
go(function () use ($db) {
$db->query($sql);
});
}
The above code throws Error:
"%s has already been bound to another coroutine#%ld, reading or writing of the same socket in multiple coroutines at the same time is not allowed."
If you like to reading socket concurrently, use Swoole Channel
or SplQueue
to build a connection pool to control the access to the connection resource.
Join 4,000+ others and never miss out on new tips, tutorials, and more.