PHP pthreads Multi-threaded installation and use

Source: Internet
Author: User
Tags flock zts
Install pthreads basically need to recompile PHP, plus--enable-maintainer-zts parameters, but with this document very few, bug will be many very many unexpected problems, build environment can only hehe, so this thing to play even, True multithreading or Python, C, etc.

First, installation

php-7.0.2 is used here.

./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

Installing Pthreads

PECL Install Pthreads

Second, Thread

<?php#1$thread = new class extends thread {public function run () {echo ' Hello World {$this->getthreadid ()}\n ";}}; $thread->start () && $thread->join (); #2class Workerthread extends Thread {public function __construct ($i) {$this->i= $i;} 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 ();}? >

Iii. Worker and Stackable

Stackables is tasks that is executed by Worker threads. You can synchronize with, read, and write stackable objects before, after, and during their execution.

<?phpclass 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;p ublic 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 ORDER BY id desc limit 1,5 '); $wor Ker->stack ($sql 1); $sql 2 = new SQLQuery (' SELECT * FROM test ORDER BY id desc limit 5,5 '); $worker->stack ($sql 2); $worke R->start (); $worker->shutdown ();? >

Four, mutual exclusion lock

What happens when a mutex is used? This can be used in situations where you need to control multiple threads at the same time with only one thread working. A simple counter program that shows the difference in the case of a mutex without a mutual lock

<?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->handle = fopen ("/tmp/counter.txt", "w+");} Public Function __destruct () {fclose ($this->handle);} Public Function Run () {if ($this->mutex) $locked =mutex::lock ($this->mutex); $counter = Intval (fgets ($this handle); $counter ++;rewind ($this->handle); Fputs ($this->handle, $counter);p rintf ("Thread #%lu says:%s\n", $ This->getthreadid (), $counter), if ($this->mutex) mutex::unlock ($this->mutex);}} There is no mutex for ($i =0; $i <50; $i + +) {$threads [$i] = new Counterthread (); $threads [$i]->start ();} Join Mutex $mutex = Mutex::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-threaded vs. shared memory

In the example of shared memory, no lock is used, it may still work, and the function of the operating memory operation itself can be locked.

<?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) ;p rintf ("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 instead want the thread to wait for our command. Thread−>wait (); Thread−>start () After the thread does not run immediately, only receive thread->notify (); After the signal is sent, the

is not run

<?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);p rintf ("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

<?phpclass Update extends Thread {public $running = false;public $row = Array ();p ublic function __construct ($row) {$thi S->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[' I d ']); $this->sql = $sql;} printf ("%s\n", $this->sql);}} Class Pool {public $pool = array ();p ublic 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 the members order by id desc"; $row = $dbh->query ($sql); $pool = new Pool (5); while ($member = $row->fetch (PDO::FETCH_ASSOC)) {while (true) {if ($pool->push ($member)) {//press into task into 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 above example is when the line Cheng executes start unified boot, the following example is to create a new thread as soon as there is idle in the thread pool.

<?phpclass Update extends Thread {public $running = false;public $row = Array ();p ublic function __construct ($row) {$thi S->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[' I d ']); $this->sql = $sql;} printf ("%s\n", $this->sql);}} 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 the members order by id desc LIMIT"; $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

<?phpclass Webworker extends Worker {public function __construct (Safelog $logger) {$this->logger = $logger;} protected $loger;} Class WebWork extends Stackable {public Function iscomplete () {return $this->complete;} Public Function Run () {$this->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 = arr Ay_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, multi-threaded file security Read and write

Lock_sh Get a shared lock (read program)

LOCK_EX Get exclusive Lock (write program

Lock_un release lock (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)) {//Type lock Ftruncate ($fp, 0);//Truncate Filefwrite ( $FP, "Write something here\n"); Fflush ($FP); Flush output before releasing the Lockflock ($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, multi-threading and data connections

Pthreads is used in conjunction with PDO, it is important to note that you need to statically declare public static $DBH and access the database connection through singleton mode.

Worker and PDO

<?phpclass work extends Stackable {public Function __construct () {}public function run () {$DBH = $this->worker->g Etconnection (); $sql = "Select Id,name from the members ORDER by id desc-Limit"; $row = $dbh->query ($sql); while ($member = $r Ow->fetch (PDO::FETCH_ASSOC)) {Print_r ($member);}}}  Class Exampleworker extends Worker {public static $DBH;p ublic 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 a database in a thread pool

# cat Pool.php<?phpclass Exampleworker extends Worker {public function __construct (Logging $logger) {$this->logger = $logger;} protected $logger;} /* The collectable class implements machinery for Pool::collect */class work extends Stackable {public Function __construc T ($number) {$this->number = $number;} Public Function Run () {$dbhost = ' db.example.com ';//database Server $dbuser = ' example.com ';//database user name $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 ' = '. $th is->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= ' succeeded ', DeposiT_time= '. $mt _trades[' Open_time ']. "' WHERE ' order ' = '". $this->number[' 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 ']);}} Class Logging extends Stackable {protected static $DBH;p ublic function __construct () {$dbhost = ' db.example.com ';//Database service Device $dbuser = ' example.com '; Database user name $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 vsprintf ( "{$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 user Name $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 ', name from accounts where deposit_time is null for the ORDER by id desc "; $row = $dbh->query ($sql), while ($account = $row->fetch (pdo::fet CH_ASSOC) {$pool->submit (new Work ($account));} $pool->shutdown ();?  >

To further improve the above procedure, we use a singleton mode $this->worker->getinstance (); The global database connection is only made once, and the thread uses the shared database connection

<?phpclass Exampleworker extends Worker {#public function __construct (Logging $logger) {# $this->logger = $logger; # } #protected $logger;p rotected static $dbh;p ublic function __construct () {}public function run () {$dbhost = ' Db.example.com '; Database server $dbuser = ' example.com '; Database user name $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 __construc T ($data) {$this->data = $data; #print_r ($data);} Public Function Run () {# $this->worker->logger->log ('%s executing 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 mobile = '". $mobile. "' WHERE id = '". $id. "'"; # printf ("%s\n", $sql); # $dbh->query ($sql); $mobile = "; $sql =" UPDATE members_digest SET mobile =: mobile WHERE id =: I D ";} 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 user name $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 the 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"; # $st h = $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 a SC "; 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 ();? >

Operations Database summary in multi-threading

In general Pthreads is still in development, there are still some deficiencies, we can also see pthreads git is constantly improving the project

Database persistent links are important, or each thread will open a database connection and then close, causing many links to time out.

<?PHP$DBH = new PDO (' Mysql:host=localhost;dbname=test ', $user, $pass, array (pdo::attr_persistent = true)); >

About PHP pthreads multi-threaded installation and use of relevant knowledge, first introduce to you here, follow up will continue to update.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.