Install pthreads basically need to recompile PHP, plus--enable-maintainer-zts parameter, but use this document very little; Bugs can be a lot of unexpected problems, build environment can only hehe, so this thing to play even if, Real multithreading or using Python, C, etc.
First, installation
This is php-7.0.2.
./configure \
--prefix=/usr/local/php7 \
--with-config-file-path=/etc \
--with-config-file-scan-dir=/ ETC/PHP.D \
--enable-debug \
--enable-maintainer-zts \
--enable-pcntl \
--enable-fpm \
-- Enable-opcache \
--enable-embed=shared \
--enable-json=shared \
--enable-phpdbg \
--with-curl= Shared \
--with-mysql=/usr/local/mysql \
--with-mysqli=/usr/local/mysql/bin/mysql_config \-
- With-pdo-mysql
Make && make install
Install Pthreads
PECL Install Pthreads
Second, Thread
<?php
#1
$thread = new class extends thread {public
function run () {
echo] Hello World {$this->gett Hreadid ()}\n ";
}
};
$thread->start () && $thread->join ();
#2
class Workerthread extends Thread {public
function __construct ($i) {
$this->i= $i;
}
The public Function run () {while
(true) {
echo $this->i. \ n ";
Sleep (1);
}}} For ($i =0 $i <50; $i + +) {
$workers [$i]=new workerthread ($i);
$workers [$i]->start ();
}
? >
Third, Worker and stackable
Stackables are tasks that are executed by Worker threads. You can synchronize with, read, and write stackable objects before, after and during their.
<?php
class SQLQuery extends stackable {public
function __construct ($sql) {
$this->sql = $sql;
} Public
function Run () {
$DBH = $this->worker->getconnection ();
$row = $dbh->query ($this->sql);
while ($member = $row->fetch (PDO::FETCH_ASSOC)) {
print_r ($member);
}}} Class Exampleworker extends Worker {public
static $dbh;
Public function __construct ($name) {
} public
function run () {
self:: $DBH = new PDO (' mysql:host= 10.0.0.30;dbname=testdb ', ' root ', ' 123456 ');
Public Function getconnection () {return
self:: $dbh;
}
}
$worker = new Exampleworker ("My Worker Thread");
$sql 1 = new SQLQuery (' SELECT * FROM test-id desc limit 1,5 ');
$worker->stack ($sql 1);
$sql 2 = new SQLQuery (' SELECT * FROM test-id desc limit 5,5 ');
$worker->stack ($sql 2);
$worker->start ();
$worker->shutdown ();
? >
Iv. Mutual-exclusion locks
Under what circumstances will a mutex be used? Can be used when you need to control multiple threads at the same time that only one thread is working. A simple counter program that indicates a different
without a mutex.
<?php $counter = 0;
$handle =fopen ("/tmp/counter.txt", "w");
Fwrite ($handle, $counter);
Fclose ($handle); Class Counterthread extends Thread {public function __construct ($mutex = null) {$this->mutex = $mutex; $this->handl
E = fopen ("/tmp/counter.txt", "w+"); The Public Function __destruct () {fclose ($this->handle),} public function run () {if ($this->mutex) $locked =mutex::lo
CK ($this->mutex);
$counter = Intval (fgets ($this->handle));
$counter + +;
Rewind ($this->handle);
Fputs ($this->handle, $counter);
printf ("Thread #%lu says:%s\n", $this->getthreadid (), $counter);
if ($this->mutex) mutex::unlock ($this->mutex); }//No Mutex for ($i =0 $i <50; $i + +) {$threads [$i] = new Counterthread (); $threads [$i]->start ();}//Join Mutex $mutex = Mut
Ex::create (TRUE);
For ($i =0 $i <50; $i + +) {$threads [$i] = new Counterthread ($mutex); $threads [$i]->start ();}
Mutex::unlock ($mutex);
For ($i =0 $i <50; $i + +) {$threads [$i]->join ();} Mutex::d Estroy ($mutex);?>
Multi-threading and shared memory
In the case of shared memory, no lock is used, and it may still work, and the working memory operation itself has the function of locking
<?php
$tmp = Tempnam (__file__, ' php ');
$key = Ftok ($tmp, ' a ');
$shmid = Shm_attach ($key);
$counter = 0;
Shm_put_var ($shmid, 1, $counter);
Class Counterthread extends Thread {public
function __construct ($shmid) {
$this->shmid = $shmid;
}
Public Function Run () {
$counter = Shm_get_var ($this->shmid, 1);
$counter + +;
Shm_put_var ($this->shmid, 1, $counter);
printf ("Thread #%lu says:%s\n", $this->getthreadid (), $counter);
}
For ($i =0 $i <100; $i + +) {
$threads [] = new Counterthread ($shmid);
}
For ($i =0 $i <100; $i + +) {
$threads [$i]->start ();
}
For ($i =0 $i <100; $i + +) {
$threads [$i]->join ();
}
Shm_remove ($shmid);
Shm_detach ($shmid);
? >
Five, thread synchronization
There are scenarios where we don't want Thread->start () to start running the program, but we want the thread to wait for our command. The thread−>wait () is Thread−>start () after the thread does not run immediately and only receives the thread->notify (); The
is not run until the signal is emitted.
<?php
$tmp = Tempnam (__file__, ' php ');
$key = Ftok ($tmp, ' a ');
$shmid = Shm_attach ($key);
$counter = 0;
Shm_put_var ($shmid, 1, $counter);
Class Counterthread extends Thread {public
function __construct ($shmid) {
$this->shmid = $shmid;
}
Public Function Run () {
$this->synchronized (function ($thread) {
$thread->wait ();
}, $this);
$counter = Shm_get_var ($this->shmid, 1);
$counter + +;
Shm_put_var ($this->shmid, 1, $counter);
printf ("Thread #%lu says:%s\n", $this->getthreadid (), $counter);
}
For ($i =0 $i <100; $i + +) {
$threads [] = new Counterthread ($shmid);
}
For ($i =0 $i <100; $i + +) {
$threads [$i]->start ();
}
For ($i =0 $i <100; $i + +) {
$threads [$i]->synchronized (function ($thread) {
$thread->notify ();
} , $threads [$i]);
}
For ($i =0 $i <100; $i + +) {
$threads [$i]->join ();
}
Shm_remove ($shmid);
Shm_detach ($shmid);
Six, thread pool
A pool class
<?php class Update extends Thread {public $running = false, public $row = Array (), Public function __construct ($row)
{$this->row = $row; $this->sql = null;} Public Function Run () {if (strlen ($this->row[' Bankno ']) > {$bankno = safenet_decrypt ($this->row[' Bankno ']
); }else{$error = sprintf ("%s,%s\r\n", $this->row[' id '), $this->row[' bankno '); File_put_contents ("Bankno_
Error.log ", $error, File_append); } if (strlen ($bankno) > 7) {$sql = sprintf ("UPDATE members Set Bankno = '%s ' WHERE id = '%s ';", $bankno, $this->row
[' ID ']);
$this->sql = $sql;
printf ("%s\n", $this->sql); Class Pool {public $pool = array (), Public function __construct ($count) {$this->count = $count;} public function Push ($row) {if (count ($this->pool) < $this->count) {$this->pool[] = new Update ($row); return true;}
else{return false;} Public Function Start () {foreach ($this->pool as $id => $worker) {$this->pool[$id]->start ();} ' public funCtion join () {foreach ($this->pool as $id => $worker) {$this->pool[$id]->join ();}} public Function clean () {
foreach ($this->pool as $id => $worker) {if (! $worker->isrunning ()) {unset ($this->pool[$id]);}} try {$dbh = new PDO ("mysql:host=". Str_replace (': ', ';p ort= ', $dbhost). ";d bname= $dbname", $dbuser, $DBPW, Array (pdo::mysql_attr_init_command => ' SET NAMES \ ' utf8\ ', pdo::mysql_attr_
COMPRESS => true));
$sql = "Select Id,bankno from DESC";
$row = $dbh->query ($sql);
$pool = new Pool (5); while ($member = $row->fetch (PDO::FETCH_ASSOC)) {while (true) {if ($pool->push ($member)) {//pressing the task into the pool break;}
else{//If the pool is full, start the thread $pool->start (); $pool->join (); $pool->clean ();}}
} $pool->start ();
$pool->join ();
$DBH = null; catch (Exception $e) {echo ' [', Date (' h:i:s '), '] ', ' system error ', $e->getmessage (), ' \ n ';}?>
Dynamic Queue thread pool
The example above is to perform start unified startup after the line Cheng, and the following example is to create a new thread as soon as there is idle in the thread pool.
<?php class Update extends Thread {public $running = false, public $row = Array (), Public function __construct ($row)
{$this->row = $row; $this->sql = null;//print_r ($this->row);} Public Function Run () {if (strlen ($this->row[' Bankno ']) > {$bankno = safenet_decrypt ($this->row[' Bankno ']
); }else{$error = sprintf ("%s,%s\r\n", $this->row[' id '), $this->row[' bankno '); File_put_contents ("Bankno_
Error.log ", $error, File_append); } if (strlen ($bankno) > 7) {$sql = sprintf ("UPDATE members Set Bankno = '%s ' WHERE id = '%s ';", $bankno, $this->row
[' ID ']);
$this->sql = $sql;
printf ("%s\n", $this->sql); The try {$dbh = new PDO ("mysql:host=". Str_replace (': ', ';p ort= ', $dbhost). ";d bname= $dbname", $dbuser, $DBPW, Array (pdo::mysql_attr_init_command => ' SET NAMES \ ' utf8\ ', pdo::mysql_attr_
COMPRESS => true));
$sql = "Select Id,bankno from desc limit 50";
$row = $dbh->query ($sql);
$pool = Array (); while ($member = $row->fetch (PDO::FETCH_ASSOC)) {$id = $member [' id ']; while (true) {if (count ($pool) < 5) {$pool [$id] = new Update ($member
);
$pool [$id]->start ();
Break
}else{foreach ($pool as $name => $worker) {if (! $worker->isrunning ()) {unset ($pool [$name]);}}}
} $DBH = null; catch (Exception $e) {echo ' "', Date (' h:i:s '), '" ', ' "System error", $e->getmessage (), "\ n";}?>
pthreads Pool class
<?php class Webworker extends Worker {public function __construct (Safelog $logger) {$this->logger = $logger;} PR
Otected $loger; Class WebWork extends Stackable {public Function iscomplete () {return $this->complete;} public Function run () {$t
His->worker->logger->log ("%s executing in Thread #%lu", __class__, $this->worker->getthreadid ());
$this->complete = true;
} protected $complete; Class Safelog extends Stackable {protected function log ($message, $args = []) {$args = Func_get_args (); if ($message
= Array_shift ($args))) {echo vsprintf ("{$message}\n", $args);}
$pool = new Pool (8, \webworker::class, [New Safelog ()]);
$pool->submit ($w =new webwork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ()); $pool->submit (New WEBWORK ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->submit (New WebWork ());
$pool->shutdown ();
$pool->collect (function ($work) {return $work->iscomplete ();}); Var_dump ($pool);
Seven, multithreading file security Read and write
Lock_sh access to shared locks (read programs)
LOCK_EX Get exclusive Lock (written program
Lock_un release locks (either shared or exclusive)
LOCK_NB If you do not want flock () to block when locked
<?php
$fp = fopen ("/tmp/lock.txt", "r+");
if (Flock ($FP, LOCK_EX)) {//For exclusive locking
ftruncate ($fp, 0);//Truncate file
fwrite ($fp, "Write something here\n");
fflush ($FP); Flush output before releasing the lock
flock ($fp, lock_un);//release lock
} else {
echo "couldn ' t get the lock!" ;
}
Fclose ($FP);
$fp = fopen ('/tmp/lock.txt ', ' r+ ');
if (!flock ($fp, LOCK_EX | LOCK_NB)) {
echo ' unable to obtain lock ';
Exit ( -1);
}
Fclose ($FP);
? >
Eight, multithreading and data Connectivity
Pthreads and PDO are used at the same time, you need to be aware of the need to statically declare the public static $DBH, and to access the database connection through a single case mode.
Worker and PDO
<?php
class Work extends stackable {public
function __construct () {
} public
function run () {
$ DBH = $this->worker->getconnection ();
$sql = "Select Id,name from desc limit";
$row = $dbh->query ($sql);
while ($member = $row->fetch (PDO::FETCH_ASSOC)) {
print_r ($member);
}}} Class Exampleworker extends Worker {public
static $dbh;
Public function __construct ($name) {
}
/
* The Run method should just prepare the environment for the work This is coming
... */Public
function run () {
self:: $DBH = new PDO (' mysql:host= ...; Dbname=example ', ' www ', ');
}
Public Function getconnection () {return
self:: $dbh;
}
}
$worker = new Exampleworker ("My Worker Thread");
$work =new work ();
$worker->stack ($work);
$worker->start ();
$worker->shutdown ();
Pool and PDO
Link database in thread pool
# cat pool.php <?php class Exampleworker extends Worker {public function __construct (Logging $logger) {$this->log
GER = $logger;
} protected $logger; }/* The collectable class implements machinery for Pool::collect */class Work extends Stackable {public Function __cons Truct ($number) {$this->number = $number;} public Function Run () {$dbhost = ' db.example.com ';//database Server $dbuser = ' EX Ample.com '; Database username $DBPW = ' password ';
Database Password $dbname = ' example_real '; $DBH = new PDO ("mysql:host= $dbhost;p ort=;d bname= $dbname", $dbuser, $DBPW, Array (Pdo::mysql_attr_init_command => '
SET NAMES \ ' utf\ ', pdo::mysql_attr_compress => true, pdo::attr_persistent => true); $sql = "Select Open_time, ' COMMENT ' from mt_trades where login= '". $this->number[' name '. "' and cmd= ' and ' COMMENT ' = ' ". $this->number[' order '].":D
Eposit ' ";
#echo $sql;
$row = $dbh->query ($sql);
$MT _trades = $row->fetch (PDO::FETCH_ASSOC); if ($mt _trades) {$row = null; $sql = "UPDATE Db_example.accoUnts SET paystatus= ' success ', Deposit_time= '. $mt _trades[' Open_time ']. "' WHERE ' order ' = '". $this->number[' an order '. "';";
$DBH->query ($sql);
#printf ("%s\n", $sql);
} $DBH = null;
printf ("Runtime:%s,%s,%s\n", Date (' y-m-d h:i:s '), $this->worker->getthreadid (), $this->number[' order '); The class Logging extends stackable {protected static $DBH; public function __construct () {$dbhost = ' db.example.com '; /database Server $dbuser = ' example.com '; Database username $DBPW = ' password '; Database Password $dbname = ' example_real '; Database name self:: $DBH = new PDO ("mysql:host= $dbhost;p ort=;d bname= $dbname", $dbuser, $DBPW, Array (pdo::mysql_attr_init_
COMMAND => ' SET NAMES \ utf\ ', pdo::mysql_attr_compress => true); } protected function log ($message, $args = []) {$args = Func_get_args (); if ($message = Array_shift ($args)) {echo VSPR
Intf ("{$message}\n", $args);
} protected function getconnection () {return self:: $DBH;}}
$pool = new Pool (, \exampleworker::class, [New Logging ()]); $dbhost = ' Db.examPle.com '; Database server $dbuser = ' example.com '; Database username $DBPW = ' password ';
Database Password $dbname = ' db_example '; $DBH = new PDO ("mysql:host= $dbhost;p ort=;d bname= $dbname", $dbuser, $DBPW, Array (Pdo::mysql_attr_init_command => '
SET NAMES \ ' utf\ ', pdo::mysql_attr_compress => true);
$sql = "SELECT ' Order", the name from accounts where deposit_time be null ORDER by id DESC ";
$row = $dbh->query ($sql); while ($account = $row->fetch (PDO::FETCH_ASSOC)) {$pool->submit (new Work ($account));} $pool->shutdown ();? >
Further improve the above program, we use the single case mode $this->worker->getinstance (); Global only once database connection, thread use shared database connection
<?php class Exampleworker extends Worker {#public function __construct (Logging $logger) {# $this->logger = $logge
R
#} #protected $logger;
protected static $DBH; Public Function __construct () {} public Function run () {$dbhost = ' db.example.com ';//database Server $dbuser = ' example.com '; Database username $DBPW = ' password '; Database Password $dbname = ' example '; Database name self:: $DBH = new PDO ("mysql:host= $dbhost;p ort=;d bname= $dbname", $dbuser, $DBPW, Array (pdo::mysql_attr_init_
COMMAND => ' SET NAMES \ utf\ ', pdo::mysql_attr_compress => true, pdo::attr_persistent => true);
} protected function getinstance () {return self:: $DBH;}} /* The collectable class implements machinery for Pool::collect */class Work extends Stackable {public Function __constr UCT ($data) {$this->data = $data; #print_r ($data);} public Function Run () {# $this->worker->logger->log ("%s E
Xecuting in Thread #%lu ", __class__, $this->worker->getthreadid ()); try {$dbh = $this->worker->getinstance ();
#print_r ($DBH);
$id = $this->data[' id '];
$mobile = Safenet_decrypt ($this->data[' mobile ');
#printf ("%d,%s \ n", $id, $mobile); if (strlen ($mobile) >) {$mobile = substr ($mobile,-);} if ($mobile = = ' null ') {# $sql = ' UPDATE members_digest SET mobi
Le = ' ". $mobile." ' WHERE id = ' ". $id." ' ";
# printf ("%s\n", $sql);
# $DBH->query ($sql);
$mobile = ';
$sql = "UPDATE members_digest SET mobile =: mobile WHERE id =: id";
}else{$sql = "UPDATE members_digest SET mobile = MD (: mobile) WHERE id =: id";} $sth = $dbh->prepare ($sql);
$sth->bindvalue (': Mobile ', $mobile);
$sth->bindvalue (': Id ', $id);
$sth->execute ();
#echo $sth->debugdumpparams (); catch (Pdoexception $e) {$error = sprintf ("%s,%s\n", $mobile, $id); File_put_contents ("Mobile_error.log", $error, File_
APPEND);
# $DBH = null;
printf ("Runtime:%s,%s,%s,%s\n", Date (' y-m-d h:i:s '), $this->worker->getthreadid (), $mobile, $id);
#printf ("Runtime:%s,%s\n", Date (' y-m-d h:i:s '), $this->number); }} $pool = new Pool (, \exampleworker::class, []); #foreach (Range (,) as $number) {# $pool->submit (New Work ($number)); #} $dbhost = ' db.example.com '; Database server $dbuser = ' example.com '; Database username $DBPW = ' password ';
Database Password $dbname = ' example '; $DBH = new PDO ("mysql:host= $dbhost;p ort=;d bname= $dbname", $dbuser, $DBPW, Array (Pdo::mysql_attr_init_command => '
SET NAMES \ ' utf\ ', pdo::mysql_attr_compress => true);
#print_r ($DBH);
# $sql = "SELECT ID, mobile from members where ID <: ID";
# $sth = $dbh->prepare ($sql);
# $sth->bindvalue (': id ',);
# $sth->execute ();
# $result = $sth->fetchall ();
#print_r ($result);
# # $sql = ' UPDATE members_digest SET mobile =: mobile WHERE id =: ID ';
# $sth = $dbh->prepare ($sql);
# $sth->bindvalue (': Mobile ', ' AA ');
# $sth->bindvalue (': id ', ');
#echo $sth->execute ();
#echo $sth->querystring;
#echo $sth->debugdumpparams (); $sql = "SELECT ID, Mobile from Members ' ORDER by ID ASC";
Limit ";
$row = $dbh->query ($sql); while ($members = $row->fetch (PDO::FETCH_ASSOC)) {# $order = $account [' Order ']; #printf ("%s\n", $order);//print_r ($members); $pool-
>submit (New Work ($members));
#unset ($account [' Order ']); } $pool->shutdown ();?>
Summary of operation database in multi-threading
Overall pthreads is still in development, there are still some deficiencies, and we can see that pthreads's git is constantly improving the project
Database persistent links are important, otherwise each thread will open a database connection and then close, causing many links to timeout.
<?php
$dbh = new PDO (' Mysql:host=localhost;dbname=test ', $user, $pass, Array (
pdo::attr_persistent => True
);
? >
About the PHP pthreads installation and use of the relevant knowledge, first to introduce to you here, follow-up will continue to update.