애플리케이션 스레드를 안전하게 만드는 방법
특히 스레드 세이프는 여러 스레드가 동일한 공유 데이터에 액세스해야 한다는 것을 의미합니다.하지만 이 정의로는 충분하지 않은 것 같습니다.
어플리케이션 스레드를 안전하게 하기 위해 해야 할 일 또는 주의해야 할 일을 적어주세요.가능하면 C/C++ 언어에 대한 답변을 주세요.
함수를 스레드 세이프로 하는 방법에는 여러 가지가 있습니다.
재진입이 가능합니다.즉, 함수에 상태가 없고 전역 변수나 정적 변수를 건드리지 않으므로 여러 스레드에서 동시에 호출할 수 있습니다.이 용어는 다른 스레드가 이미 함수에 있는 동안 한 스레드가 함수에 들어갈 수 있도록 허용하기 때문에 유래되었습니다.
중요한 섹션이 있을 수 있습니다.이 용어는 자주 언급되지만, 솔직히 저는 중요한 데이터를 선호합니다.여러 스레드에서 공유되는 데이터에 코드가 닿을 때마다 중요한 섹션이 발생합니다.그래서 저는 그 중요한 데이터에 초점을 맞추고 싶습니다.
뮤텍스를 올바르게 사용하면 중요한 데이터에 대한 액세스를 동기화하여 스레드 안전하지 않은 수정으로부터 적절히 보호할 수 있습니다.뮤텍스와 록은 매우 유용하지만, 강력한 파워를 가지고 있으면 큰 책임을 지게 됩니다.같은 스레드 내에서 같은 뮤텍스를 2회 잠그지 마십시오(즉, 셀프 데드록).둘 이상의 뮤텍스를 획득할 경우 교착 상태가 발생할 위험이 높아지므로 주의해야 합니다.뮤텍스를 사용하여 데이터를 일관되게 보호해야 합니다.
모든 기능이 스레드 세이프이고 모든 공유 데이터가 올바르게 보호되어 있다면 응용 프로그램은 스레드 세이프여야 합니다.
Crazy Eddie가 말했듯이, 이것은 큰 주제입니다.부스트 스레드를 읽고 그에 따라 사용할 것을 권장합니다.
낮은 수준의 경고: 컴파일러가 스테이트먼트의 순서를 변경할 수 있기 때문에 스레드의 안전성이 저하될 수 있습니다.코어가 여러 개일 경우 각 코어는 자체 캐시를 가지고 있으며 스레드 안전을 위해 캐시를 적절하게 동기화해야 합니다.또, 컴파일러가 스테이트먼트의 순서를 변경하지 않아도, 하드웨어가 순서를 변경할 수 있습니다.따라서 완전하고 확실한 스레드 안전은 현재 실현되지 않습니다.그러나 99.99%를 얻을 수 있으며, 이 문제를 해결하기 위해 컴파일러 벤더 및 CPU 제조업체와 협력하고 있습니다.
어쨌든 클래스를 스레드 세이프로 만들기 위한 체크리스트를 찾고 있다면:
- 스레드 간에 공유되는 모든 데이터 식별(데이터를 놓치면 보호할 수 없음)
- 을
boost::mutex m_mutex공유 멤버 데이터에 액세스하려고 할 때마다 사용합니다(공유 데이터는 클래스의 개인 데이터이므로 적절하게 보호되고 있는지 확인할 수 있습니다). - 지구촌을 청소하다어차피 지구대회는 안 좋으니까, 지구대회는 아무 문제 없이 잘 해내길 바라.
- :
static키워드를 지정합니다.실은 스레드 세이프가 아닙니다.그래서 싱글톤을 하려고 하면 제대로 작동하지 않아요. - 이중 체크 잠금 패러다임을 주의해 주십시오.그것을 사용하는 대부분의 사람들은 몇 가지 미묘한 방법으로 잘못 알고 있으며, 낮은 수준의 경고로 인해 파손되기 쉽습니다.
그건 불완전한 체크리스트네요.생각나면 추가하겠습니다만, 이것으로 충분히 시작할 수 있을 것 같습니다.
두 가지:
1. 글로벌을 사용하지 않도록 합니다.현재 글로벌이 있는 경우 스레드 단위 상태 구조의 멤버로 만든 후 스레드가 해당 구조를 공통 함수에 전달하도록 합니다.
예를 들어 다음과 같이 시작합니다.
// Globals
int x;
int y;
// Function that needs to be accessed by multiple threads
// currently relies on globals, and hence cannot work with
// multiple threads
int myFunc()
{
return x+y;
}
상태 구조를 추가하면 코드는 다음과 같이 됩니다.
typedef struct myState
{
int x;
int y;
} myState;
// Function that needs to be accessed by multiple threads
// now takes state struct
int myFunc(struct myState *state)
{
return (state->x + state->y);
}
이제 x와 y를 매개 변수로 전달하면 어떨까요?그 이유는 이 예가 단순화이기 때문입니다.실제 상태 구조에는 20개의 필드가 있을 수 있으며, 이들 파라미터의 대부분을 4~5개의 함수로 전달하는 것은 어려운 일입니다.여러 매개 변수를 전달하는 대신 하나의 매개 변수를 전달하는 것이 좋습니다.
2. 스레드에 공유할 필요가 있는 공통 데이터가 있는 경우 중요한 섹션과 세마포어를 조사해야 합니다.스레드 중 하나가 데이터에 액세스할 때마다 다른 스레드를 차단한 다음 공유 데이터 액세스가 완료되면 해당 스레드를 차단 해제해야 합니다.
클래스의 메서드에 배타적으로 액세스하려면 이러한 함수에서 잠금을 사용해야 합니다.
다른 유형의 잠금:
atomic_flg_lck 사용:
class SLock
{
public:
void lock()
{
while (lck.test_and_set(std::memory_order_acquire));
}
void unlock()
{
lck.clear(std::memory_order_release);
}
SLock(){
//lck = ATOMIC_FLAG_INIT;
lck.clear();
}
private:
std::atomic_flag lck;// = ATOMIC_FLAG_INIT;
};
atomic 사용:
class SLock
{
public:
void lock()
{
while (lck.exchange(true));
}
void unlock()
{
lck = true;
}
SLock(){
//lck = ATOMIC_FLAG_INIT;
lck = false;
}
private:
std::atomic<bool> lck;
};
뮤텍스 사용:
class SLock
{
public:
void lock()
{
lck.lock();
}
void unlock()
{
lck.unlock();
}
private:
std::mutex lck;
};
Windows 전용:
class SLock
{
public:
void lock()
{
EnterCriticalSection(&g_crit_sec);
}
void unlock()
{
LeaveCriticalSection(&g_crit_sec);
}
SLock(){
InitializeCriticalSectionAndSpinCount(&g_crit_sec, 0x80000400);
}
private:
CRITICAL_SECTION g_crit_sec;
};
atomic 및 atomic_flag는 스레드를 스핀 카운트로 유지합니다.뮤텍스는 실잠만 잔다.대기시간이 너무 길면 아마 실컷 자는 것이 나을 것이다.마지막 "CRITIAL_Section"은 시간이 소비될 때까지 스레드를 스핀 카운트로 유지한 후 스레드가 sleeve 상태가 됩니다.
이러한 중요한 섹션의 사용법은 무엇입니까?
unique_ptr<SLock> raiilock(new SLock());
class Smartlock{
public:
Smartlock(){ raiilock->lock(); }
~Smartlock(){ raiilock->unlock(); }
};
사자성어를 사용해서.임계 섹션을 잠그는 생성자와 잠금을 해제하는 소멸자.
예
class MyClass {
void syncronithedFunction(){
Smartlock lock;
//.....
}
}
이 실장은 스레드 세이프 및 예외 세이프입니다.변수 잠금이 스택에 저장되기 때문에 함수 범위가 종료되었을 때(함수의 종료 또는 예외) 소멸자가 호출됩니다.
이것이 도움이 되기를 바랍니다.
감사합니다!!
하나의 아이디어는 프로그램을 큐를 통해 통신하는 스레드 집합이라고 생각하는 것입니다.각 스레드에는 1개의 큐가 있으며 이러한 큐는 공유 데이터 동기화 방식(뮤텍스 등)과 함께 모든 스레드에 공유됩니다.
그런 다음 큐가 부족하거나 오버플로하지 않도록 하려면 생산자/소비자 문제를 "해결"하십시오.http://en.wikipedia.org/wiki/Producer-consumer_problem
스레드의 현지화를 유지하고 큐를 통해 복사본을 전송하여 데이터를 공유하기만 하면 됩니다.또한 스레드에는 안전하지 않은 (대부분의) GUI 라이브러리나 여러 스레드의 정적 변수에 액세스하지 않아도 됩니다.
언급URL : https://stackoverflow.com/questions/5125241/how-to-make-an-application-thread-safe
'programing' 카테고리의 다른 글
| Java 클래스가 구현된 인터페이스에서 주석을 상속하지 않는 이유는 무엇입니까? (0) | 2022.10.22 |
|---|---|
| mariadb 서버 로컬 설치로 mariadb의 도커를 실행할 수 있습니까? (0) | 2022.10.22 |
| PHP를 통해 이메일로 HTML 전송 (0) | 2022.10.22 |
| stdClass 개체를 다른 클래스로 변환/캐스팅합니다. (0) | 2022.10.22 |
| 많은 인수를 메서드에 전달하기 위한 베스트 프랙티스? (0) | 2022.10.22 |