首先就是构造函数:
constructorTThread.Create(CreateSuspended:Boolean);
begin
inheritedCreate;
AddThread;
FSuspended:=CreateSuspended;
FCreateSuspended:=CreateSuspended;
FHandle:=BeginThread(nil,0,@ThreadProc,Pointer(Self),CREATE_SUSPENDED,FThreadID);
ifFHandle=0then
raiseEThread.CreateResFmt(@SThreadCreateError,[SysErrorMessage(GetLastError)]);
end;
虽然这个构造函数没有多少代码,但却可以算是最重要的一个成员,因为线程就是在这里被创建的。
在通过 Inherited 调用 TObject.Create 后,第一句就是调用一个过程:AddThread,其源码如下:
procedureAddThread;
begin
InterlockedIncrement(ThreadCount);
end;
同样有一个对应的 RemoveThread:
procedureRemoveThread;
begin
InterlockedDecrement(ThreadCount);
end;
它们的功能很简单,就是通过增减一个全局变量来统计进程中的线程数。只是这里用于增减变量的并不是常用的 Inc/Dec 过程,而是用
了 InterlockedIncrement/InterlockedDecrement 这一对过程,它们实现的功能完全一样,都是对变量加一或减一。但它们有一个最
大的区别,那就是 InterlockedIncrement/InterlockedDecrement 是线程安全的。即它们在多线程下能保证执行结果正确,而 Inc/
Dec 不能。或者按操作系统理论中的术语来说,这是一对“原语”操作。
以加一为例来说明二者实现细节上的不同:
一般来说,对内存数据加一的操作分解以后有三个步骤:
1、 从内存中读出数据
2、 数据加一
3、 存入内存
现在假设在一个两个线程的应用中用 Inc 进行加一操作可能出现的一种情况:
1、 线程 A 从内存中读出数据(假设为 3)
2、 线程 B 从内存中读出数据(也是 3)
3、 线程 A 对数据加一(现在是 4)
4、 线程 B 对数据加一(现在也是 4)
5、 线程 A 将数据存入内存(现在内存中的数据是 4)
6、 线程 B 也将数据存入内存(现在内存中的数据还是 4,但两个线程都对它加了一,应该是 5 才对,所以这里出现了错误的结果)