如何在 php 中跨线程共享全局变量?
How to share global variable across thread in php?
在多线程中,全局变量或资源在线程之间共享。
我在 c
中使用 pthread 库
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *worker(void *);
int ctr = 0;
pthread_mutex_t lock;
int main(int argc, char *argv[])
{
pthread_t t[2];
int i = 0;
//~ pthread_mutex_init(&lock, NULL);
while(i < 2)
{
pthread_create(&t[i], NULL, &worker, NULL);
i++;
}
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
//~ pthread_mutex_destroy(&lock);
//~ pthread_join(t[1], NULL);
return 0;
}
void *worker(void *arg)
{
//~ pthread_mutex_lock(&lock);
//~ int ctr = 0;
ctr += 1;
printf("job %d started\n", ctr);
sleep(1);
//~ ctr += 1;
printf("job %d finished\n", ctr);
//~ pthread_mutex_unlock(&lock);
}
此代码输出:
job 1 started
job 2 started
job 2 finished
job 2 finished
在此代码中,变量 ctr
在线程之间共享,因此其他线程对该变量所做的更改对另一个线程可见(除非已完成对某些 mutexes
的调用)。
我在 php 中尝试过,但没有成功(使用 php pthreads
)。
这是我的 php 代码:
global $ctr;
Class WorkerThread extends Worker
{
private $thread_id;
//~ public static $ctr = 0;
private $mutext;
public function WorkerThread($mutex = NULL)
{
//~ $this->ctr = $ctr;
$this->mutex = $mutex;
$this->start();
}
public function run()
{
//~ Mutex::lock($this->mutex);
$new_line = php_sapi_name() == "cli" ? PHP_EOL : "<br>";
//~ global $ctr;
$ctr = 0;
$ctr += 1;
echo "Thread " . $ctr . " started" . " [ " . $this->getThreadId() . " ]" . $new_line;
sleep(1);
echo "Thread " . $ctr . " Finished" . " [ " . $this->getThreadId() . " ]" . $new_line;
//~ var_dump($this);
//~ Mutex::unlock($this->mutex);
}
}
//~ $mutex = Mutex::create();
$i = 0;
$worker = array();
while($i < 2)
{
$worker[$i] = new WorkerThread();
//~ $worker[$i]->start();
$i++;
}
foreach(range(0, 1) as $t)
$worker[$t]->join();
//~ Mutex::destroy($mutex);
此代码的输出:
Thread 1 started [ -1257948352 ]
Thread 1 started [ -1267893440 ]
Thread 1 Finished [ -1257948352 ]
Thread 1 Finished [ -1267893440 ]
变量ctr
(全局)没有像上面的c代码那样被线程更新?
如何在 php 中做到这一点(跨线程共享资源)?
通常,线程在与启动它们的进程相同的地址 space 中执行。
因此,在C中,新线程可以直接访问主程序堆栈上的变量。
当你在PHP中创建一个新线程时,它有一个单独的堆,它必须在一个单独的地址space中执行。
这意味着默认情况下,您不能在线程之间共享全局状态。
这是 PHP 的正常线程模型 - 不共享。
pthreads 所做的是引入能够在许多上下文中操作的对象,并且能够在这些上下文之间共享数据。
等效的 PHP 代码可能类似于:
<?php
class Atomic extends Threaded {
public function __construct($value = 0) {
$this->value = $value;
}
public function inc() {
return $this->value++;
}
/* ... */
private $value;
}
class Test extends Thread {
public function __construct(Atomic $atomic) {
$this->atomic = $atomic;
}
public function run() {
$this->atomic->inc();
}
private $atomic;
}
$atomic = new Atomic();
$threads = [];
for ($thread = 0; $thread < 2; $thread++) {
$threads[$thread] = new Test($atomic);
$threads[$thread]->start();
}
foreach ($threads as $thread)
$thread->join();
var_dump($atomic);
?>
请注意,不直接使用 Mutex(并且已从最新版本的 pthreads 中删除)。使用 Mutex 是危险的,因为您没有足够的执行控制权来安全地使用它们;如果你锁定了一个互斥量,然后无论出于何种原因解释器出现致命错误,你将无法释放互斥量,死锁将随之而来...
也没有必要,因为对对象范围的单指令操作是原子的。
在执行排除时,您可以使用 Threaded::synchronized
API 来取得很好的效果。
需要排除的地方,run
方法可能看起来更像:
public function run() {
$this->atomic->synchronized(function($atomic){
/* exclusive */
$atomic->inc();
}, $this->atomic);
}
最后,一堂命名事物的课...
你似乎是,并且被原谅的印象是,在 Posix 线程(标准,pthread)和 pthreads,PHP 扩展之间有一些相似之处...
pthreads
,PHP 扩展碰巧 使用 Posix 线程,但它没有 实现 任何类似 Posix 线程的东西。
名称 pthreads
应该表示 PHP 个线程...命名事物很难。
在多线程中,全局变量或资源在线程之间共享。 我在 c
中使用 pthread 库#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *worker(void *);
int ctr = 0;
pthread_mutex_t lock;
int main(int argc, char *argv[])
{
pthread_t t[2];
int i = 0;
//~ pthread_mutex_init(&lock, NULL);
while(i < 2)
{
pthread_create(&t[i], NULL, &worker, NULL);
i++;
}
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
//~ pthread_mutex_destroy(&lock);
//~ pthread_join(t[1], NULL);
return 0;
}
void *worker(void *arg)
{
//~ pthread_mutex_lock(&lock);
//~ int ctr = 0;
ctr += 1;
printf("job %d started\n", ctr);
sleep(1);
//~ ctr += 1;
printf("job %d finished\n", ctr);
//~ pthread_mutex_unlock(&lock);
}
此代码输出:
job 1 started
job 2 started
job 2 finished
job 2 finished
在此代码中,变量 ctr
在线程之间共享,因此其他线程对该变量所做的更改对另一个线程可见(除非已完成对某些 mutexes
的调用)。
我在 php 中尝试过,但没有成功(使用 php pthreads
)。
这是我的 php 代码:
global $ctr;
Class WorkerThread extends Worker
{
private $thread_id;
//~ public static $ctr = 0;
private $mutext;
public function WorkerThread($mutex = NULL)
{
//~ $this->ctr = $ctr;
$this->mutex = $mutex;
$this->start();
}
public function run()
{
//~ Mutex::lock($this->mutex);
$new_line = php_sapi_name() == "cli" ? PHP_EOL : "<br>";
//~ global $ctr;
$ctr = 0;
$ctr += 1;
echo "Thread " . $ctr . " started" . " [ " . $this->getThreadId() . " ]" . $new_line;
sleep(1);
echo "Thread " . $ctr . " Finished" . " [ " . $this->getThreadId() . " ]" . $new_line;
//~ var_dump($this);
//~ Mutex::unlock($this->mutex);
}
}
//~ $mutex = Mutex::create();
$i = 0;
$worker = array();
while($i < 2)
{
$worker[$i] = new WorkerThread();
//~ $worker[$i]->start();
$i++;
}
foreach(range(0, 1) as $t)
$worker[$t]->join();
//~ Mutex::destroy($mutex);
此代码的输出:
Thread 1 started [ -1257948352 ]
Thread 1 started [ -1267893440 ]
Thread 1 Finished [ -1257948352 ]
Thread 1 Finished [ -1267893440 ]
变量ctr
(全局)没有像上面的c代码那样被线程更新?
如何在 php 中做到这一点(跨线程共享资源)?
通常,线程在与启动它们的进程相同的地址 space 中执行。
因此,在C中,新线程可以直接访问主程序堆栈上的变量。
当你在PHP中创建一个新线程时,它有一个单独的堆,它必须在一个单独的地址space中执行。
这意味着默认情况下,您不能在线程之间共享全局状态。
这是 PHP 的正常线程模型 - 不共享。
pthreads 所做的是引入能够在许多上下文中操作的对象,并且能够在这些上下文之间共享数据。
等效的 PHP 代码可能类似于:
<?php
class Atomic extends Threaded {
public function __construct($value = 0) {
$this->value = $value;
}
public function inc() {
return $this->value++;
}
/* ... */
private $value;
}
class Test extends Thread {
public function __construct(Atomic $atomic) {
$this->atomic = $atomic;
}
public function run() {
$this->atomic->inc();
}
private $atomic;
}
$atomic = new Atomic();
$threads = [];
for ($thread = 0; $thread < 2; $thread++) {
$threads[$thread] = new Test($atomic);
$threads[$thread]->start();
}
foreach ($threads as $thread)
$thread->join();
var_dump($atomic);
?>
请注意,不直接使用 Mutex(并且已从最新版本的 pthreads 中删除)。使用 Mutex 是危险的,因为您没有足够的执行控制权来安全地使用它们;如果你锁定了一个互斥量,然后无论出于何种原因解释器出现致命错误,你将无法释放互斥量,死锁将随之而来...
也没有必要,因为对对象范围的单指令操作是原子的。
在执行排除时,您可以使用 Threaded::synchronized
API 来取得很好的效果。
需要排除的地方,run
方法可能看起来更像:
public function run() {
$this->atomic->synchronized(function($atomic){
/* exclusive */
$atomic->inc();
}, $this->atomic);
}
最后,一堂命名事物的课...
你似乎是,并且被原谅的印象是,在 Posix 线程(标准,pthread)和 pthreads,PHP 扩展之间有一些相似之处...
pthreads
,PHP 扩展碰巧 使用 Posix 线程,但它没有 实现 任何类似 Posix 线程的东西。
名称 pthreads
应该表示 PHP 个线程...命名事物很难。