草庐IT

PHP - 中断或暂停 pthread 的执行

coder 2024-01-04 原文

如何从主上下文中中断线程的执行?

在下面的代码片段中——如何在不破坏线程的情况下停止线程的操作?

class ReadFileThread extends Thread
{
    public function __construct($file, $chunk = 1024)
    {
        $this->file = $file;

        $this->chunk = $chunk;
    }

    public function run()
    {
        if(is_file($this->file) && is_readable($this->file))
        {
            $fh = fopen($this->file, 'rb');

            while(!feof($fh))
            {
                $content = fread($fh, $this->chunk);
            }

            fclose($fh);
        }
    }
}

$num = 10;
$threads = [];

for($i = 0; $i < $num; $i++)
{
    $thread = new ReadFileThread('/path/to/10gig_file.txt', 1024);

    $threads[] = $thread;

    // I start the thread, now it's detached from the main context and is reading the file asynchronously
    $thread->start();
}

// The interesting part - I want to random 1 thread whose operation of file reading I want to interrupt
$to_interrupt = $threads[rand(0, $num)];

// How to interrupt the thread without destroying it? I want its context preserved

最佳答案

RandomSeeds 答案很接近,但对竞争条件开放。

<?php
class FileReader extends Thread {
    public $file;
    public $pause;

    public function __construct($file) {
        $this->file = $file;
        $this->pause = false;
    }

    public function run() {
        if (($handle = fopen($this->file, "rb"))) {
            $len = 0;
            do {
                $this->synchronized(function(){
                    if ($this->paused) {
                        printf(
                            "\npausing %lu ...\n", $this->getThreadId());
                        $this->wait();
                    }
                });

                $data = fread($handle, 1024);
                $len += strlen($data);

                if (($len % 2) == 0) {
                    printf( 
                        "\r\rread %lu", $len);
                }
            } while (!feof($handle));

            fclose($handle);
        }
    }

    public function pause() {
        return $this->synchronized(function(){
            return ($this->paused = true);
        });
    }

    public function unpause() {
        return $this->synchronized(function(){
            $this->paused = false;      
            if ($this->isWaiting()) {
                return $this->notify();
            }
        });
    }
}

function do_something($time) {
    $start = time();

    while (($now = time()) < ($start + $time)) {
        usleep(100);
        if (($now % 2) == 0) {
            echo ".";
        }
    }

    echo "\n";
}

$reader = new FileReader("/path/to/big/file.ext");
$reader->start();

sleep(2);
$reader->pause();
do_something(rand(2, 4));
$reader->unpause();
sleep(2);
$reader->pause();
do_something(rand(2, 4));
$reader->unpause();
sleep(2);
$reader->pause();
do_something(rand(2, 4));
$reader->unpause();
?>

重要的是,用于同步目的的变量只能在同步块(synchronized block)中访问,我省略了停止/退出函数的实现,但它的逻辑大致相同,如 RandomSeeds 示例所示。

竞争条件潜伏在:

public function mine($data) {
    /* anyone can set doSynchronization at any time */
    if ($this->doSynchronization) {

        $this->synchronize(function(){
            /* checking the predicate in here is safer */
            $this->wait();
        });
    }
}

好:

public function mine($data) {
    $this->synchronize(function(){
        if ($this->doSynchronization) {
            $this->wait();
        }
    });
}

极端:

public function mine($data) {
    $this->synchronize(function(){
        while ($this->doSynchronization) {
            $this->wait();
        }
    });
}

posix 标准总是让你以极端的方式编写它,我不那么大惊小怪,任何适合你的。这种极端代码的原因是,必须允许线程接收信号而不是它正在等待的信号,许多低级别信号可能导致线程从调用 pthread_cond_wait 中唤醒;在这样的循环中检查谓词可以防止规范中所谓的虚假唤醒……但这种极端措施也会导致不良的副作用;这些线程收到低电平信号的原因是因为他们有必要采取某种行动,忽略它很容易导致堆栈的不同部分死锁,因为它希望你的线程死掉(或做其他事情, die 是一个例子)当它被发出信号时......

关于PHP - 中断或暂停 pthread 的执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20195956/

有关PHP - 中断或暂停 pthread 的执行的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  3. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  4. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

  5. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  6. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

    我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

  7. ruby - ruby 乘法语句中星号中断语法前的空格 - 2

    在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个:classCdefx42endendm=C.new现在这将给出“错误数量的参数”:m.x*m.x这将给出“语法错误,意外的tSTAR,期待$end”:2/m.x*m.x这里的解析器到底发生了什么?我使用Ruby1.9.2和2.1.5进行了测试。 最佳答案 *用于运算符(42*42)和参数解包(myfun*[42,42])。当你这样做时:m.x*m.x2/m.x*m.xRuby将此解释为参数解包,而不是*运算符(即乘法)。如果您不熟悉它,参数解包(有时也称为“spl

  8. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  9. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  10. ruby - 在 ASP 页面上 Mechanize 中断 - 2

    require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

随机推荐