Delphi 다중 스레드의 스레드 부분 저장 관리

4196 단어 Delphi
비록 다선정은 많은 문제를 해결할 수 있지만, 동시에 그것은 우리에게 많은 문제를 가져다 주었다.그 중에서 주요한 문제는 전역 변수나 핸들 같은 전역 자원에 어떻게 접근합니까?또한 한 라인의 어떤 사건이 다른 라인의 다른 시간 이전(또는 이후)에 발생하도록 확보해야 할 때 어떻게 해야 합니까?Delphi에서 제공하는 스레드 부분 저장소와 A P I를 사용하여 스레드를 동기화하는 방법을 설명합니다.
여기서는 먼저 스레드 부분 저장에 대해 이야기하고, 다음 편에서는 스레드 동기화에 대해 이야기한다
스레드 로컬 저장소
모든 스레드는 서로 다른 실행 경로를 대표하기 때문에 한 스레드 내부에서만 사용하는 데이터 저장 방식이 가장 좋다.이러한 목적을 달성하려면 다음 세 가지 방법이 있습니다.
1) 첫 번째이자 가장 간단한 방식은 국부 변수(창고에 기반을 둔다)이다.
모든 스레드가 각자의 창고에 있기 때문에 각 스레드는 국부 변수의 사본을 가지고 있기 때문에 서로 영향을 주지 않을 것이다.
2) 두 번째 방법은 관련 정보를 각자의 라인 대상에 저장하는 것이다
3) 세 번째 방식은 Delphi의 키워드threadvar로 변수를 성명하여 운영체제급의 스레드 국부 저장을 이용하는 것이다
 
1. TThread 파생 대상에 정보 저장
관련 정보를 TThread 파생 대상에 저장하는 것은 루트 부분적으로 선택할 수 있는 기술이다.키워드threadvar를 사용하는 기술에 비해 이런 방식은 더욱 간단하고 효과적이다.예를 들어, 너는 하나의 라인 대상에 아래의 정보를 추가할 수 있다
type

    TMyThread = class(TThread)

    private

        FLocalInt: Integer;

        FLocalStr: String;

        ..

        ..

    end;


알림: 방문 루트 대상의 데이터가 방문 루트의 국부 변수보다 10배 빠르기 때문에, 가능한 한 루트 전용 정보를 루트 대상에 저장해야 합니다.과정이나 함수의 생존 기간에만 의미 있는 변수는 국부 변수로 성명해야 한다
 
2.threadvar: API 스레드 로컬 스토리지
앞에서 말했듯이 국부 변수는 모든 라인에 하나의 복사본이 있지만 응용 프로그램의 전역 변수는 모든 라인에 의해 공유된다.예를 들어 전역 변수의 값을 설정하고 표시하는 과정이 더 있다고 가정하십시오.문자열을 전달하면 이 전역 변수를 설정합니다.빈 문자열을 전달하면 전체 변수의 값을 표시합니다.이 절차는 다음과 같이 정의됩니다.
var

    GolbalStr: String;

procedure SetShowStr(const S: String);

begin

    if S = '' then

        MessageBox(0, PChar(GlobalStr), 'The string is ...', MB_OK)

    else

        GlobalStr:= S;

end;


만약 어떤 코드에서 이 과정을 호출한다면 약간의 문제가 발생할 수 있다.그것을 호출할 때, 먼저 설정한 다음에 표시할 수 있기 때문이다.문제는 두 개 이상의 라인이 존재할 수도 있다는 점이다.한 스레드가 이 프로세스를 호출하여 문자열을 설정할 때, 다른 스레드도 이 프로세스를 호출하여 GlobalStr 변수의 값을 설정할 수 있습니다.운영 체제가 CPU 시간을 이전 라인에 다시 분배할 때, 이 라인이 설정한 값은 이미 실망스럽게 잃어버릴 수 있다
이 문제를 해결하기 위해서, Win32는 루트 국부 저장소라고 불리는 방식을 제공합니다. 이것은 첫 번째 실행 루트에서 전역 변수의 복사를 만들 수 있습니다.Delphi는 키워드 threadvar를 이용하여 이 기능을 봉인합니다.
threadvar 키워드에서 국부적으로 저장된 변수를 설명할 수 있습니다.다음은 로컬 변수 GlobalStr에 대한 설명입니다.
threadvar

    GlobalStr: String;


다음은 스레드 국부 저장의 용법을 보여 준다.프로그램의 메인 창에 단추가 있습니다. 이 단추를 누르면 Global Str 변수의 값을 설정하고 표시합니다.GlobalStr 변수의 값이 설정되어 표시되는 스레드를 만듭니다.스레드를 만든 후 GlobalStr 변수의 값을 주 스레드에서 다시 설정하고 표시합니다
먼저 var과threadvar로 Global Str 변수를 설명하고 이 프로그램을 실행하면 출력에서 다른 것을 볼 수 있습니다
interface

uses

    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

    Dialogs, StdCtrls;



type

    TMainForm = class(TForm)

        Button1:TButton;

        procedure Button1Click(Sender: TObject);

    private

        {...}

    public

        {...}

    end;



var

    MainForm: TMainForm;



implementation

{$R *.DFM}



var

//threadvar

    GlobalStr: String;



type

    TTLSThread = class(TThread)

    private

        FNewStr: String;

    protected

        Procedure Execute; override;

    public

        cpnstructor Create(Const ANewStr: String);

    end;



procedure SetShowStr(const S: String);

begin

    if S = '' then

        MessageBox(0, PChar(GlobalStr), 'The string is ...', MB_OK)

    else

        GlobalStr:= S;

end;



constructor TTLSThread.Create(const ANewStr: String);

begin

    FNewStr:= ANewStr;

    inherited Create(False);

end;



procedure TTSThread.Execute;

begin

    FreeOnTerminate:= True;

    SetShowStr(FNewStr);

    SetShowStr('');

end;



procedure TMianForm.Button1Click(Sender: TObject);

begin

    SetShowStr('Hello World');

    SetShowStr('');

    TTLSThread.Create('Dilbert');

    Sleep(100);

    SetShowStr('');

end;



end.


참고: 데모 프로그램에서 스레드가 생성된 후 Win32 API 프로세스 Sleep()이 호출되었습니다.이 과정의 성명은 다음과 같다.
procedure Sleep(dwMillseconds: DWORD); stdcall;


Sleep () 프로세스는 현재 스레드가 매개 변수dwMillseconds가 지정한 시간 내에 CPU 시간을 분배할 필요가 없다는 것을 운영체제에 알려 줍니다.이 호출을 삽입하는 것은 많은 작업이 발생할 때 어떤 라인을 실행하는지 임의적으로 하는 것입니다
일반적으로, 매개 변수dwMillseconds를 0으로 설정할 수 있습니다. 비록 현재 스레드가 정말로 '수면' 되지는 않지만, 운영체제는 CPU 시간을 다른 우선순위가 같거나 높은 스레드에 나누어 줍니다.
슬립(Sleep)의 신비로운 시간 조정 문제를 조심해야 한다.슬립 () 은 아마도 너의 기계에 특별한 문제가 생겼을 것이다.이런 문제는 다른 기계에서는 재현할 수 없을 것이다

좋은 웹페이지 즐겨찾기