Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从usleep唤醒一个std::线程_C++_Multithreading - Fatal编程技术网

C++ 从usleep唤醒一个std::线程

C++ 从usleep唤醒一个std::线程,c++,multithreading,C++,Multithreading,考虑以下示例: #include <iostream> #include <fstream> #include <unistd.h> #include <signal.h> #include <thread> void sleepy() { usleep(1.0E15); } int main() { std :: thread sleepy_thread(sleepy); // Wake it up s

考虑以下示例:

#include <iostream>
#include <fstream>
#include <unistd.h>

#include <signal.h>
#include <thread>

void sleepy() {
    usleep(1.0E15);
}

int main() {
    std :: thread sleepy_thread(sleepy);

    // Wake it up somehow...?

    sleepy_thread.join();
}
#包括
#包括
#包括
#包括
#包括
虚无困倦{
usleep(1.0E15);
}
int main(){
标准:线程休眠线程(休眠);
//不知怎么把它唤醒。。。?
sleepy_thread.join();
}
这里我们有一条永远沉睡的线。我想加入它,而不必永远等待它从美国睡眠计划中自发醒来。有没有办法从外人的“嘿,伙计,醒醒!”中分辨出来,这样我就可以在合理的时间内加入它

我绝对不是线程方面的专家,所以如果可能的话,不要假设任何事情。

一种可能的方法:(有很多方法可以实现……而且在线程中使用睡眠也不是一个好主意)


只需使用一个信号量,调用而不是
usleep
,在调用
join
之前先调用睡眠一小段时间,然后查看变量是否已更改

#include <atomic>
#include <unistd.h>
#include <thread>

std::atomic<int> sharedVar(1);
void sleepy()
{
    while (sharedVar.load())
    {
        usleep(500);
    }
}

int main()
{
    std :: thread sleepy_thread(sleepy);
    // wake up
    sharedVar.store(0);
}
#包括
#包括
#包括
std::原子共享dvar(1);
虚无困倦
{
while(sharedVar.load())
{
美国LEEP(500);
}
}
int main()
{
标准:线程休眠线程(休眠);
//醒醒
sharedVar.store(0);
}
“有没有办法从外人那里分辨出来”嘿,伙计,醒醒!“,以便我能在合理的时间内加入它?”

不,没有根据C++标准机制来做的。

好吧,为了唤醒你的线程,你需要一个机制,让其他线程控制它。此外,还有一个不推荐使用的POSIX函数:

第6期 更新说明以避免在应用要求中使用术语“必须”

此功能已标记为过时。

IEEE Std 1003.1-2001/Cor 2-2004第XSH/TC2/D6/144项适用,将描述从“进程的信号掩码”更新为“线程的信号掩码”,并添加了一条声明,即
usleep()
函数不需要重入

您无法控制另一个线程,它将调用该函数。
对于任何其他
sleep()
函数,即使从中声明,也是如此


如其他答案或评论中所述,您需要使用线程函数中的可计时同步机制,如a或a。

否,不可能使用标准库中的线程

一种可能的解决方法是为使用
condition\u变量::sleep\u以及
mutex
和布尔条件

#include <mutex>
#include <thread>
#include <condition_variable>

std::mutex mymutex;
std::condition_variable mycond;
bool flag = false;

void sleepy() {
     std::unique_lock<std::mutex> lock(mymutex);
     mycond.wait_for( lock,
                      std::chrono::seconds(1000),
                      []() { return flag; } );
}

int main()
{
    std :: thread sleepy_thread(sleepy);

    {
       std::lock_guard<std::mutex> lock(mymutex);
       flag = true;
       mycond.notify_one();
    }

    sleepy_thread.join();
}
#包括
#包括
#包括
std::mutex mymutex;
std::条件变量mycond;
布尔标志=假;
虚无困倦{
std::唯一锁(mymutex);
我的命令。等待(锁定),
标准时间:秒(1000),
[](){返回标志;});
}
int main()
{
标准:线程休眠线程(休眠);
{
std::lock_guard lock(mymutex);
flag=true;
我的命令通知你一个();
}
sleepy_thread.join();
}
或者,您可以使用实现中断点概念的库:

#包括
虚无困倦
{
//此线程::sleep是一个中断点。
boost::this_线程::sleep_for(boost::chrono::seconds(1000));
}
int main()
{
boost::线程t(sleepy);
t、 中断();
t、 join();
}

其他答案是,您可以使用定时静音来完成此任务。我创建了一个使用定时互斥锁的小类来阻止“睡眠”线程,如果您想尽早“唤醒”线程,请释放互斥锁。标准库为
timed_mutex
提供了一个名为
try_lock_for
的函数,该函数将尝试锁定一段时间的互斥锁,然后继续执行(并返回故障指示)

这可以封装在一个类中,如下面的实现,它只允许单个调用唤醒等待的线程。它还可以通过包含一个用于等待时间序列的
waitUntil
函数来改进,该函数对应于
timed_mutex
的另一个定时等待函数
try_lock_until
,但我将把它作为一个练习留给感兴趣的人,因为这似乎是一个简单的修改



IIRC
usleep(1.0E15)上的示例和使用
不接受
浮点值
双精度
值???@πάνταῥεῖ: 那又怎样
1e15
可隐式转换为
int
。虽然这是一个相当多的
int
@LightnessRacesinOrbit“虽然这是一个相当多的
int
”是我的观点。总之,这是一个很大的值。@OP您还应该注意,
usleep()
是。发送一个信号怎么样?“在线程中使用睡眠不是一个好主意”为什么呢?您应该充实答案的
std::mutex
部分。这个代码是非法的,因为对
sharedVar
的两个访问冲突,根据C++标准,不可能是非法的。你是说没有定义的行为吗?如果sleepy在一个循环中读取sharedVar的旧版本,它将在一个循环后读取较新的值。问题不是sleepy可能读取旧版本。问题是任何事情都可能发生。至少
std::atomic sharedVar=1请@πάνταῥεῖ: 最好不要这样做,因为它无法编译。我使用pthread的答案被否决了。这也使用了一个pHooLoad库。旗语实际上是C++标准吗?我能想到的最好的代理是。我实际上非常喜欢这个主意。。。!为什么会被否决?这个例子使用Linux特定的
usleep
,为什么我们不能在这里使用Linux特定的信号量?
#include <mutex>
#include <thread>
#include <condition_variable>

std::mutex mymutex;
std::condition_variable mycond;
bool flag = false;

void sleepy() {
     std::unique_lock<std::mutex> lock(mymutex);
     mycond.wait_for( lock,
                      std::chrono::seconds(1000),
                      []() { return flag; } );
}

int main()
{
    std :: thread sleepy_thread(sleepy);

    {
       std::lock_guard<std::mutex> lock(mymutex);
       flag = true;
       mycond.notify_one();
    }

    sleepy_thread.join();
}
#include <boost/thread/thread.hpp>

void sleepy()
{
    // this_thread::sleep_for is an interruption point.
    boost::this_thread::sleep_for( boost::chrono::seconds(1000) );
}

int main()
{
    boost::thread t( sleepy );

    t.interrupt();
    t.join();

}
#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>

// one use wakable sleeping class
class InterruptableSleeper{
    std::timed_mutex
        mut_;
    std::atomic_bool
        locked_; // track whether the mutex is locked
    void lock(){ // lock mutex
        mut_.lock();
        locked_ = true;
    }
    void unlock(){ // unlock mutex
        locked_ = false;
        mut_.unlock();
    }
public:
    // lock on creation
    InterruptableSleeper() {
        lock();
    }
    // unlock on destruction, if wake was never called
    ~InterruptableSleeper(){
        if(locked_){
            unlock();
        }
    }
    // called by any thread except the creator
    // waits until wake is called or the specified time passes
    template< class Rep, class Period >
    void sleepFor(const std::chrono::duration<Rep,Period>& timeout_duration){
        if(mut_.try_lock_for(timeout_duration)){
            // if successfully locked, 
            // remove the lock
            mut_.unlock();
        }
    }
    // unblock any waiting threads, handling a situation
    // where wake has already been called.
    // should only be called by the creating thread
    void wake(){
        if(locked_){
            unlock();
        }
    }
};
void printTimeWaited(
  InterruptableSleeper& sleeper, 
  const std::chrono::milliseconds& duration){
    auto start = std::chrono::steady_clock::now();
    std::cout << "Started sleep...";
    sleeper.sleepFor(duration);
    auto end = std::chrono::steady_clock::now();
    std::cout 
        << "Ended sleep after "
        << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
        << "ms.\n";
}

void compareTimes(unsigned int sleep, unsigned int waker){
    std::cout << "Begin test: sleep for " << sleep << "ms, wakeup at " << waker << "ms\n";
    InterruptableSleeper
        sleeper;
    std::thread
        sleepy(&printTimeWaited, std::ref(sleeper), std::chrono::milliseconds{sleep});
    std::this_thread::sleep_for(std::chrono::milliseconds{waker});
    sleeper.wake();
    sleepy.join();
    std::cout << "End test\n";
}

int main(){

    compareTimes(1000, 50);
    compareTimes(50, 1000);

}
Begin test: sleep for 1000ms, wakeup at 50ms
Started sleep...Ended sleep after 50ms.
End test
Begin test: sleep for 50ms, wakeup at 1000ms
Started sleep...Ended sleep after 50ms.
End test