C++, Linux, Multithreading 환경에서 std::sleep_for(std::chrono::hours::max())가 즉시 반환되는 이유
std::sleep_for 함수의 작동 방식
std::sleep_for
함수는 지정된 시간 동안 스레드를 일시 중단시킵니다. std::chrono::hours::max()
값은 24855 years, 23 hours, 59 minutes, 59 seconds, 999 milliseconds를 나타내는 std::chrono::duration
객체입니다. 이 값을 std::sleep_for
함수에 전달하면 스레드가 약 24855년 동안 일시 중단될 것으로 기대됩니다.
Linux 시스템의 nanosleep 시스템 콜
std::sleep_for
함수는 Linux 시스템에서 nanosleep()
시스템 콜을 사용하여 스레드를 일시 중단시킵니다. nanosleep()
시스템 콜은 두 개의 인수를 받습니다:
requested_time
: 스레드가 일시 중단될 시간을 나타내는 구조체remaining_time
:
requested_time
값이 timespec
구조체에 저장됩니다. timespec
구조체는 다음 두 가지 필드로 구성됩니다:
tv_sec
: 초 단위의 시간
std::chrono::hours::max() 값과 nanosleep 시스템 콜
std::chrono::hours::max()
값은 timespec
구조체에 저장할 수 있는 값보다 훨씬 큽니다. timespec
구조체에서 tv_sec
필드는 32비트 정수로 표현되므로 최대 2147483647초 (약 68년)까지만 저장할 수 있습니다. std::chrono::hours::max()
값은 이 값을 훨씬 초과합니다.
따라서 std::sleep_for(std::chrono::hours::max())
함수를 호출하면 nanosleep()
시스템 콜은 requested_time
값을 timespec
구조체에 저장할 수 없고 즉시 반환됩니다.
문제 해결 방법
std::sleep_for(std::chrono::hours::max())
함수가 즉시 반환되는 문제를 해결하려면 다음과 같은 방법을 사용할 수 있습니다:
std::this_thread::sleep_for
함수 사용:
std::this_thread::sleep_for
함수는 현재 스레드를 지정된 시간 동안 일시 중단시킵니다. 이 함수는 std::chrono::hours::max()
값을 인수로 받을 수 있습니다.
std::this_thread::sleep_for(std::chrono::hours::max());
while
루프 사용:
while
루프를 사용하여 지정된 시간 동안 반복적으로 잠을 자도록 스레드를 구현할 수 있습니다.
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
// ...
}
- 조건 변수 사용:
조건 변수를 사용하여 스레드가 특정 조건이 충족될 때까지 잠을 자도록 구현할 수 있습니다.
std::mutex mtx;
std::condition_variable cv;
void thread_func() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return condition_is_met(); });
// ...
}
예제 코드
#include <iostream>
#include <chrono>
int main() {
std::cout << "Starting..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "Finished!" << std::endl;
return 0;
}
이 코드를 실행하면 다음과 같은 출력이 생성됩니다.
Starting...
Finished!
다음은 while
루프를 사용하여 10초 동안 반복적으로 잠을 자도록 스레드를 구현하는 C++ 코드 예시입니다.
#include <iostream>
#include <chrono>
int main() {
std::cout << "Starting..." << std::endl;
int i = 0;
while (i < 10) {
std::this_thread::sleep_for(std::chrono::seconds(1));
i++;
}
std::cout << "Finished!" << std::endl;
return 0;
}
Starting...
Finished!
#include <iostream>
#include <chrono>
#include <mutex>
#include <condition_variable>
bool condition_is_met = false;
std::mutex mtx;
std::condition_variable cv;
void thread_func() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return condition_is_met; });
// ...
}
int main() {
std::cout << "Starting..." << std::endl;
std::thread t(thread_func);
// ...
{
std::unique_lock<std::mutex> lock(mtx);
condition_is_met = true;
}
cv.notify_one();
t.join();
std::cout << "Finished!" << std::endl;
return 0;
}
Starting...
Finished!
주의 사항
C++에서 스레드를 일시 중단시키는 대체 방법
std::this_thread::sleep_for 함수
std::this_thread::sleep_for
함수는 현재 스레드를 지정된 시간 동안 일시 중단시킵니다. 이 함수는 가장 간단하고 직관적인 방법입니다.
std::this_thread::sleep_for(std::chrono::seconds(10));
while 루프
int i = 0;
while (i < 10) {
std::this_thread::sleep_for(std::chrono::seconds(1));
i++;
}
조건 변수
std::mutex mtx;
std::condition_variable cv;
bool condition_is_met = false;
void thread_func() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return condition_is_met; });
// ...
}
int main() {
std::thread t(thread_func);
// ...
{
std::unique_lock<std::mutex> lock(mtx);
condition_is_met = true;
}
cv.notify_one();
t.join();
return 0;
}
boost::thread::sleep 함수
Boost C++ 라이브러리를 사용하면 boost::thread::sleep
함수를 사용하여 스레드를 일시 중단시킬 수 있습니다.
#include <boost/thread.hpp>
boost::thread::sleep(boost::posix_time::seconds(10));
std::atomic 클래스
std::atomic
클래스를 사용하여 원자성을 유지하면서 스레드를 일시 중단시킬 수 있습니다.
std::atomic<bool> flag = false;
void thread_func() {
while (!flag) {
// ...
}
// ...
}
int main() {
std::thread t(thread_func);
// ...
flag = true;
t.join();
return 0;
}
선택 가이드
사용할 방법은 상황에 따라 다릅니다.
- 간단한 경우
std::this_thread::sleep_for
함수를 사용하는 것이 가장 좋습니다. - 더 정교한 제어가 필요한 경우
while
루프나 조건 변수를 사용하는 것이 좋습니다. - 원자성을 유지해야 하는 경우
std::atomic
클래스를 사용해야 합니다.
c++ linux multithreading