스레드 안전성
Thread safety스레드 안전은 멀티 스레드 코드에 적용할 수 있는 컴퓨터 프로그래밍 개념입니다.스레드 세이프 코드는 모든 스레드가 올바르게 동작하고 의도하지 않은 상호 작용 없이 설계 사양을 충족하도록 하는 방식으로만 공유 데이터 구조를 조작합니다.스레드 세이프 데이터 [1][2]구조를 만들기 위한 다양한 전략이 있습니다.
프로그램은 공유 어드레스 공간에서 여러 스레드의 코드를 동시에 실행할 수 있으며, 이들 스레드는 다른 스레드의 거의 모든 메모리에 액세스할 수 있다.스레드 안전은 동기화에 의해 실제 제어 흐름과 프로그램 텍스트 간의 대응 관계를 재정립함으로써 멀티스레드 환경에서 코드가 실행될 수 있도록 하는 속성입니다.
나사산 안전성 수준
소프트웨어 라이브러리는 특정 스레드 안전 보장을 제공할 수 있습니다.예를 들어 동시 읽기는 스레드 안전이 보장되지만 동시 쓰기는 그렇지 않을 수 있습니다.이러한 라이브러리를 사용하는 프로그램이 스레드 세이프인지 여부는 이러한 보증과 일치하는 방식으로 라이브러리를 사용하는지에 따라 달라집니다.
스레드 [3][4][5][6]안전성에 대해서는 벤더마다 약간 다른 용어를 사용합니다.
- 스레드 세이프:여러 스레드를 동시에 사용하여 액세스 할 경우 구현에 레이스 조건이 발생하지 않음을 보증합니다.
- 조건부 안전: 다른 스레드가 다른 오브젝트에 동시에 액세스 할 수 있어 공유 데이터에 대한 접근이 레이스 조건으로부터 보호됩니다.
- 스레드 세이프 없음: 데이터 구조에 다른 스레드로 동시에 액세스해서는 안 됩니다.
스레드 안전성 보증에는 일반적으로 다양한 형태의 교착 상태를 방지하거나 제한하는 설계 단계와 동시 성능을 극대화하기 위한 최적화가 포함됩니다.그러나 데드록은 라이브러리 자체와는 무관한 콜백 및 아키텍처 계층화 위반에 의해 발생할 수 있기 때문에 데드록 프리 보증이 항상 주어지는 것은 아닙니다.
구현 접근법
아래에서는 나사산 안전성을 달성하기 위해 경주 조건을 피하기 위한 두 가지 접근법에 대해 논의한다.
첫 번째 접근법 클래스는 공유 상태를 회피하는 데 중점을 두고 있으며 다음과 같은 내용을 포함합니다.
- 재진입
- 스레드에 의해 부분적으로 실행되거나 동일한 스레드에 의해 실행되거나 다른 스레드에 의해 동시에 실행되어도 원래의 실행을 올바르게 완료할 수 있도록 코드를 작성합니다.이를 위해서는 상태 정보를 정적 변수나 전역 변수 또는 기타 비 로컬 상태가 아닌 각 실행에 대해 로컬 변수(일반적으로 스택)에 저장해야 합니다.로컬이 아닌 모든 상태는 원자 연산을 통해 액세스해야 하며 데이터 구조도 재진입해야 합니다.
- 스레드 로컬 스토리지
- 변수는 각 스레드에 고유한 개인 복사가 있도록 현지화됩니다.이러한 변수는 서브루틴 및 기타 코드 경계에 걸쳐 값을 유지하며 각 스레드에 대해 로컬이기 때문에 스레드 안전합니다.이러한 변수는 액세스 하는 코드가 다른 스레드에 의해 동시에 실행될 수 있습니다.
- 불변의 객체
- 구성 후에는 개체 상태를 변경할 수 없습니다.이는 읽기 전용 데이터만 공유되고 고유한 스레드 안전성이 확보된다는 것을 의미합니다.그런 다음 기존 개체를 수정하는 대신 새 개체를 생성하는 방식으로 변경 가능(비정수) 작업을 구현할 수 있습니다.이 접근법은 기능 프로그래밍의 특징이며 Java, C# 및 Python 문자열 구현에서도 사용됩니다(불변 객체 참조).
두 번째 접근법은 동기 관련 접근법으로 공유 상태를 피할 수 없는 상황에서 사용됩니다.
- 상호 배타
- 공유 데이터에 대한 액세스는 한 번에 하나의 스레드만 읽고 쓸 수 있도록 하는 메커니즘을 사용하여 직렬화됩니다.부적절한 사용은 교착 상태, 라이브록, 자원 고갈 등의 부작용을 초래할 수 있으므로 상호 배제의 통합에 대해 잘 생각해 볼 필요가 있다.
- 원자 작전
- 공유 데이터는 다른 스레드에 의해 중단될 수 없는 원자 연산을 사용하여 액세스됩니다.이 경우 일반적으로 런타임 라이브러리에서 사용할 수 있는 특수한 기계어 명령을 사용해야 합니다.조작은 원자성이기 때문에 공유 데이터는 다른 스레드가 액세스하는 방법에 관계없이 항상 유효한 상태로 유지됩니다.원자 연산은 많은 스레드 잠금 메커니즘의 기초를 형성하고 상호 배타적 프리미티브를 구현하기 위해 사용됩니다.
예
다음 Java 코드에서는 Java 키워드를 동기화하면 스레드 세이프가 됩니다.
학급 계산대 { 사적인 인트 i = 0; 일반의 동기화된 무효 주식회사() { i++; } }
C 프로그래밍 언어에서는 각 스레드에 자체 스택이 있습니다.단, 스태틱 변수는 스택에 유지되지 않으며 모든 스레드가 해당 변수에 대한 동시 액세스를 공유합니다.동일한 기능을 실행하는 동안 여러 스레드가 겹치면 다른 스레드가 체크 도중 한 스레드에 의해 스태틱 변수가 변경될 수 있습니다.대부분의 경우 적절하게 컴파일되어 실행될 수 있는 이 진단하기 어려운 논리 오류를 레이스 조건이라고 합니다.이를 회피하는 일반적인 방법 중 하나는 다른 공유 변수를 (상호 제외에서) "잠금" 또는 "뮤텍스"로 사용하는 것입니다.
다음 C 코드에서는 함수는 스레드 세이프이지만 재진입하지 않습니다.
# 포함하다 <pthread.h> 인트 increment_counter () { 정적인 인트 계산대 = 0; 정적인 pthread_syslogx_t 뮤텍스 = PTHREAD_MUTEX_이니셜라이저; // 한 번에 하나의 스레드만 증가 가능 pthread_syslogx_lock(&뮤텍스); ++계산대; // 다른 스레드가 값을 더 늘리기 전에 값을 저장합니다. 인트 결과 = 계산대; pthread_syslogx_syslog(&뮤텍스); 돌아가다 결과; }
위의 경우,increment_counter
공유에 대한 모든 액세스를 동기화하기 위해 뮤텍스가 사용되므로 문제 없이 다른 스레드로 호출할 수 있습니다.counter
변수.그러나 이 함수가 재진입 인터럽트 핸들러에서 사용되며 뮤텍스가 잠겨 있는 동안 두 번째 인터럽트가 발생하면 두 번째 루틴이 영원히 중단됩니다.인터럽트 서비스는 다른 인터럽트를 무효로 할 수 있기 때문에 시스템 전체에 장애가 발생할 수 있습니다.
C++11의 잠금 프리 아토믹스를 사용하여 스레드 세이프 및 재진입 모두 같은 기능을 구현할 수 있습니다.
# 포함하다 <원자성> 인트 increment_counter () { 정적인 표준::원자핵의< >인트> 계산대(0); // 인크리먼트는 아토믹하게 이루어집니다. 인트 결과 = ++계산대; 돌아가다 결과; }
「 」를 참조해 주세요.
레퍼런스
- ^ Kerrisk, Michael (2010). The Linux Programing Interface. No Starch Press. p. 655.
- ^ "Multithreaded Programming Guide". Oracle Corporation. November 2010.
A procedure is thread safe when the procedure is logically correct when executed simultaneously by several threads.
- ^ "Reentrancy and Thread-Safety Qt 5.6". Qt Project. Retrieved 2016-04-20.
- ^ "ip::tcp – 1.51.0". Boost.org. Retrieved 2013-10-16.
- ^ "API thread safety classifications". Publib.boulder.ibm.com. 1998-06-09. Retrieved 2013-10-16.[데드링크]
- ^ "MT Interface Safety Levels – Multithreaded Programming Guide". Docs.oracle.com. 2010-11-01. Retrieved 2013-10-16.
외부 링크
- Java Q&A Experts (20 April 1999). "Thread-safe design (4/20/99)". JavaWorld.com. Retrieved 2012-01-22.
- TutorialsDesk (30 Sep 2014). "Synchronization and Thread Safety Tutorial with Examples in Java". TutorialsDesk.com. Retrieved 2012-01-22.
- Venners, Bill (1 August 1998). "Design for thread safety". JavaWorld.com. Retrieved 2012-01-22.
- Suess, Michael (15 October 2006). "A Short Guide to Mastering Thread-Safety". Thinking Parallel. Retrieved 2012-01-22.