[multithreading] 스레드 세이프는 무엇을 의미합니까?

최근에 UI 스레드가 아닌 스레드에서 텍스트 상자에 액세스하려고했지만 예외가 발생했습니다. “코드가 스레드로부터 안전하지 않다”는 내용이 나와서 결국 위임 (MSDN의 샘플이 도움이 됨)을 작성하고 대신 호출했습니다.

하지만 그래도 모든 추가 코드가 필요한 이유를 이해하지 못했습니다.

업데이트 : 확인하면 심각한 문제가 발생합니까?

Controls.CheckForIllegalCrossThread..blah =true



답변

Eric Lippert“스레드 안전”이라고 부르는 것은 무엇입니까? Wikipedia에서 찾은 스레드 안전성의 정의에 대해.

링크에서 추출한 3 가지 중요한 사항 :

“여러 스레드에서 동시에 실행하는 동안 올바르게 작동하는 코드는 스레드로부터 안전합니다.”

“특히 동일한 공유 데이터에 액세스하기 위해 여러 스레드에 대한 요구를 충족해야합니다.…”

“… 그리고 주어진 시간에 단 하나의 스레드에서만 액세스 할 수있는 공유 데이터의 필요성.”

읽을만한 가치가 있습니다!


답변

가장 간단한 용어로 threadsafe는 여러 스레드에서 액세스하는 것이 안전함을 의미합니다. 프로그램에서 여러 스레드를 사용하고 각각 공통 데이터 구조 또는 메모리의 위치에 액세스하려고 할 때 여러 가지 나쁜 일이 발생할 수 있습니다. 따라서 이러한 나쁜 일을 방지하기 위해 추가 코드를 추가합니다. 예를 들어, 두 사람이 동시에 같은 문서를 쓰고 있다면 두 번째로 저장할 사람이 첫 번째 사람의 작업을 덮어 씁니다. 스레드를 안전하게 만들려면 사람 2가 문서를 편집 할 수 있도록 허용하기 전에 사람 1이 작업을 완료 할 때까지 기다려야합니다.


답변

위키 백과 에는 스레드 안전성에 대한 기사가 있습니다.

정의 페이지 (광고를 건너 뛰어야합니다. 죄송합니다)는 다음과 같이 정의합니다.

컴퓨터 프로그래밍에서 스레드 안전은 스레드 간의 원치 않는 상호 작용없이 여러 프로그래밍 스레드에서 호출 할 수있는 프로그램 부분 또는 루틴을 나타냅니다.

스레드는 프로그램의 실행 경로입니다. 단일 스레드 프로그램에는 스레드가 하나만 있으므로이 문제가 발생하지 않습니다. 사실상 모든 GUI 프로그램에는 다중 실행 경로가 있으므로 스레드가 두 개 이상 있습니다. 하나는 GUI 표시를 처리하고 사용자 입력을 처리하기위한 것이고 다른 하나는 실제로 프로그램 작업을 수행하기위한 것입니다.

이는 프로그램이 작동하는 동안 UI가 계속 응답하도록하기 위해 장기 실행 프로세스를 비 UI 스레드로 오프로드하여 수행합니다. 이러한 스레드는 한 번 생성되어 프로그램의 수명 동안 존재하거나 필요할 때 생성되고 완료되면 파괴 될 수 있습니다.

이러한 스레드는 종종 디스크 I / O, 화면에 결과 출력 등과 같은 일반적인 작업을 수행해야하기 때문에 이러한 코드 부분은 여러 스레드에서 호출되는 것을 처리 할 수있는 방식으로 작성되어야합니다. 동시. 여기에는 다음과 같은 내용이 포함됩니다.

  • 데이터 사본 작업
  • 중요한 코드 주위에 잠금 추가

답변

간단히 말해 스레드 안전이란 문제가 발생하지 않고 동시에 여러 스레드에서 메서드 또는 클래스 인스턴스를 사용할 수 있음을 의미합니다.

다음 방법을 고려하십시오.

private int myInt = 0;
public int AddOne()
{
    int tmp = myInt;
    tmp = tmp + 1;
    myInt = tmp;
    return tmp;
}

이제 스레드 A와 스레드 B는 모두 AddOne ()을 실행하려고합니다. 그러나 A가 먼저 시작하고 myInt (0)의 값을 tmp로 읽습니다. 이제 어떤 이유로 스케줄러는 스레드 A를 중지하고 스레드 B로 실행을 연기하기로 결정합니다. 스레드 B는 이제 myInt 값 (여전히 0)을 자체 변수 tmp로 읽어들입니다. 스레드 B는 전체 메서드를 완료하므로 결국 myInt = 1이 반환됩니다. 이제 스레드 A의 차례입니다. 스레드 A는 계속됩니다. 그리고 tmp에 1을 추가합니다 (tmp는 스레드 A의 경우 0 임). 그리고이 값을 myInt에 저장합니다. myInt는 다시 1입니다.

따라서이 경우 AddOne 메서드가 두 번 호출되었지만 메서드가 스레드 안전 방식으로 구현되지 않았기 때문에 myInt 값은 예상대로 2가 아니라 첫 번째 스레드가 완료되기 전에 두 번째 스레드가 변수 myInt를 읽었으므로 1입니다. 업데이트.

사소하지 않은 경우 스레드로부터 안전한 메서드를 만드는 것은 매우 어렵습니다. 그리고 꽤 많은 기술이 있습니다. Java에서는 메서드를 동기화 된 것으로 표시 할 수 있습니다. 즉, 주어진 시간에 하나의 스레드 만 해당 메서드를 실행할 수 있습니다. 다른 스레드는 줄을 서서 기다립니다. 이렇게하면 메서드 스레드가 안전 해지지 만 메서드에서 수행 할 작업이 많으면 많은 공간이 낭비됩니다. 또 다른 기술은 ‘메서드의 작은 부분 만 동기화 된 것으로 표시’하는 것입니다.잠금 또는 세마포어를 만들고이 작은 부분을 잠그면 (일반적으로 중요 섹션이라고 함). 잠금없는 스레드 안전으로 구현 된 메서드도 있습니다. 즉, 여러 스레드가 문제를 일으키지 않고 동시에 경쟁 할 수있는 방식으로 빌드되었습니다. 하나의 원자 호출을 실행합니다. 원자 적 호출은 중단 할 수없고 한 번에 하나의 스레드에서만 수행 할 수있는 호출입니다.


답변

평신도에 대한 실제 사례는

인터넷과 모바일 뱅킹이 가능한 은행 계좌가 있고 계좌에 $ 10 만 있다고 가정 해 보겠습니다. 모바일 뱅킹을 사용하여 다른 계좌로 잔액을 이체하고 그 동안 동일한 은행 계좌로 온라인 쇼핑을했습니다. 이 은행 계좌가 스레드 세이프가 아닌 경우 은행은 동시에 두 가지 거래를 수행 할 수 있도록 허용하고 은행은 파산합니다.

Threadsafe는 여러 스레드가 동시에 객체에 액세스하려고해도 객체의 상태가 변경되지 않음을 의미합니다.


답변

“Java Concurrency in Practice”책에서 더 많은 설명을 얻을 수 있습니다.

런타임 환경에 의한 스레드 실행의 예약 또는 인터리빙에 관계없이 여러 스레드에서 액세스 할 때 클래스가 올바르게 작동하고 호출 코드 부분에서 추가 동기화 또는 기타 조정없이 클래스가 스레드로부터 안전합니다.


답변

모듈은 다중 스레드 및 동시 사용에 직면하여 불변을 유지할 수 있음을 보장하는 경우 스레드로부터 안전합니다.

여기서 모듈은 데이터 구조, 클래스, 객체, 메서드 / 프로 시저 또는 함수일 수 있습니다. 기본적으로 범위가 지정된 코드 및 관련 데이터입니다.

보증은 잠재적으로 특정 CPU 아키텍처와 같은 특정 환경으로 제한 될 수 있지만 이러한 환경에서는 유지되어야합니다. 환경에 대한 명시적인 구분이 없으면 일반적으로 코드가 컴파일되고 실행될 수있는 모든 환경에 대해 유지된다는 것을 암시하는 것으로 간주됩니다.

스레드에 안전하지 않은 모듈 다중 스레드 및 동시 사용에서 올바르게 작동 할 수 있지만 이는 신중한 설계보다 운과 우연에 더 가깝습니다. 일부 모듈이 아래로 파손되지 않더라도 다른 환경으로 이동하면 파손될 수 있습니다.

멀티 스레딩 버그는 종종 디버그하기 어렵습니다. 그들 중 일부는 가끔 발생하는 반면 다른 일부는 공격적으로 나타납니다.이 역시 환경에 따라 다를 수 있습니다. 미묘하게 잘못된 결과 또는 교착 상태로 나타날 수 있습니다. 예측할 수없는 방식으로 데이터 구조를 엉망으로 만들 수 있으며, 코드의 다른 원격 부분에 불가능 해 보이는 다른 버그가 나타날 수 있습니다. 매우 응용 프로그램에 따라 다를 수 있으므로 일반적인 설명을 제공하기가 어렵습니다.