Starting in D5 referring to strings and dynamic arrays will be thread-safe. In D5, access to the reference count is protected. This makes strings work correctly in multithreaded applications.Reference counting for Long Strings is not thread safe on multi-processor machines. The Bug was fixed in Delphi 5.http://www.efg2.com/Lab/Library/UseNet/1999/1119c.txt
function ThreadFun(p:Pointer): LongInt; stdcall; var Test: String; I: integer; begin for I :=0 to 1000 do begin Test := 'Test!'; Test := Test + 'Test!'; end; end;procedure TForm1.Button1Click(Sender: TObject); var H: THandle; ThreadID: DWORD; I: Integer; begin for i:=1 to 10 do // 测试一个和十个 H := CreateThread(nil, 0, @ThreadFun, nil, 0, ThreadID); end; 你也可以把string 类型(线程不安全,至少我一直这么觉得)换成系统标准类型(线程安全). 标准类型是不会报错的
剛剛查了資料,并且驗證了... 參考<Delphi in a Nut Shell>第四章--P103 有關線程安全說明如下: reading long strings and dynamic arrays is thread-safe, but writting is not. Refering to a string or dynamic array might change the reference count, but delphi protects the reference count to ensure thread safety. when changing a string or dynamic array, though, you should use a critical section, just as you would when changing any other variable. GS : string; implementation{$R *.dfm}function ThreadProc(p: Pointer): LongInt ; stdcall; begin while GS<>'' do //這樣沖突的機會較大 begin GS := GS + 'sss'; end; end; procedure TForm1.Button1Click(Sender: TObject); var id : Cardinal; i,count: Integer; begin count := 2; GS := '111'; for i:=1 to count do begin CreateThread(nil,SizeOf(Pointer),@ThreadProc,nil,0,id); end; end; 以上測試,若是有修改則會沖突,地址訪問非法。若是僅僅是讀出,則不會有問題 如改為:function ThreadProc(p: Pointer): LongInt ; stdcall; var s : string; begin while GS<>'' do begin s := s + GS ; end; end;
貌似运行了5分钟崩溃
ThreadLog('');
LeaveCriticalSection(CS);
begin
EnterCriticalSection(CS);
ThreadLog('');
LeaveCriticalSection(CS);
TMemo(
List.Objects[List.IndexOf(IntToStr(GetCurrentThreadId()))]
).Lines.Add(FormatDateTime('[yyyy-mm-dd hh:nn:ss.zzz]: ', Now) + IntToStr(GetCurrentThreadId()));
LeaveCriticalSection(CS);
end;点开始,就报错啊,楼主?
procedure ThreadLog(Const msg: String);
参数为string 是线程不安全的对String的大多数操作,都涉及到全局堆栈的操作。相对单线程的系统
来讲,使用String类型绝对不会出错,而多线程,则存在潜在的冲突的机会。特别是
大量的String类型运算,一般会引起系统堆竞争操作,则及有可能发生严重的存储冲
突,而导致系统崩溃。
但是频繁调用则会出问题
比如你在线程中操作VCL对象,你没做同步处理,有时候也不报错
In D5, access to the reference count is protected. This makes strings
work correctly in multithreaded applications.Reference counting for Long Strings is not thread safe on multi-processor machines.
The Bug was fixed in Delphi 5.http://www.efg2.com/Lab/Library/UseNet/1999/1119c.txt
我用D7執行的你的代碼,并無問題。你是開發環境是?
建議將線程改為delphi自帶的TThread,執行更新memo時,用Synchronize(ThreadLog),試看看。另外string應該是線程安全的。
function ThreadFun(p:Pointer): LongInt; stdcall;
var
Test: String;
I: integer;
begin
for I :=0 to 1000 do
begin
Test := 'Test!';
Test := Test + 'Test!';
end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
H: THandle;
ThreadID: DWORD;
I: Integer;
begin
for i:=1 to 10 do // 测试一个和十个
H := CreateThread(nil, 0, @ThreadFun, nil, 0, ThreadID);
end;
你也可以把string 类型(线程不安全,至少我一直这么觉得)换成系统标准类型(线程安全).
标准类型是不会报错的
參考<Delphi in a Nut Shell>第四章--P103 有關線程安全說明如下:
reading long strings and dynamic arrays is thread-safe, but writting is not.
Refering to a string or dynamic array might change the reference count, but
delphi protects the reference count to ensure thread safety. when changing a
string or dynamic array, though, you should use a critical section, just as you
would when changing any other variable. GS : string;
implementation{$R *.dfm}function ThreadProc(p: Pointer): LongInt ; stdcall;
begin
while GS<>'' do //這樣沖突的機會較大
begin
GS := GS + 'sss';
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
id : Cardinal;
i,count: Integer;
begin
count := 2;
GS := '111';
for i:=1 to count do
begin
CreateThread(nil,SizeOf(Pointer),@ThreadProc,nil,0,id);
end;
end;
以上測試,若是有修改則會沖突,地址訪問非法。若是僅僅是讀出,則不會有問題
如改為:function ThreadProc(p: Pointer): LongInt ; stdcall;
var
s : string;
begin
while GS<>'' do
begin
s := s + GS ;
end;
end;
線程1在修改字串時,還沒結束,此時中斷,由線程2執行,線程2可正常訪問到 字串所在地址。cpu時間片一到,又切換到線程1,線程1繼續執行while內的動作。此時,線程1訪問字串的地址還是它本身上一次處理的。
由于之前線程2對字串修改,產生寫復制,因為地址空間發生變化,原先線程1上下文環境所記錄的字串的地址已經是無效的了,所以產生地址訪問非法的錯誤...以上個人理解,僅供參考,不足之處,請指正...
查下了delphi help , IsMultiThread设置为true,表示内存管理器应该支持多线程。