web开发桌面应用程序 delphi开发安卓步骤


web开发桌面应用程序 delphi开发安卓步骤

文章插图
当你有两个或者两个以上的线程同时运行,并且他们共同操作的同一块数据时,我们必须要对其进行保护,否则因为时间切片或者一些其他原因造成的延时都会让你的程序产生错误的计算结果 。即使做两个线程访问共享整数变量这样简单的事情也可能导致完全的灾难
线程之间共享什么数据首先,值得确切知道每个进程和每个线程存储的状态 。每个线程都有自己的程序计数器和处理器状态 。这意味着线程通过代码独立进行 。每个线程也有自己的堆栈,因此局部变量本身就是每个线程的本地变量,并且这些变量不存在同步问题 。
程序中的全局数据可以在线程之间自由共享,因此这些变量可能存在同步问题 。当然,如果变量是全局可访问的,但只有一个线程使用它,则没有问题 。
Delphi提供了threadvar关键字 。这允许声明全局变量,其中为每个线程创建变量的副本 。此功能使用不多,因为将这些变量放在TThread类中通常更方便,因此为每个创建的TThread后代创建一个变量实例 。
共享数据的原子性为了理解如何使线程协同工作,有必要理解原子性的概念 。
所谓的原子性是指某一组动作是一个整体,它不可分割,要么一起成功,要么一起失败 。就好比银行转账,转账这个东西由两步完成取出、存入,必须两个都成功才可以算成功,不允许出现一半成功一半失败
当线程执行原子操作时,这意味着所有其他线程将操作视为尚未启动或已完成 。一个线程不可能在“行为”中捕获另一个线程 。如果线程之间没有执行同步,那么几乎所有操作都是非原子的 。我们举一个简单的例子 。考虑 这段代码
vara: integer;begina := a + 1;end;如果两个单独的线程使用它来递增共享变量A,即使是这些微不足道的代码也会导致问题 。这个单个pascal语句在汇编程序级别分解为三个操作 。
从存储器读取A到处理器寄存器 。将1添加到处理器寄存器 。将处理器寄存器的内容写入内存中的A.即使在单个处理器机器上,多个线程执行此代码也可能导致问题 。之所以这样做是因为调度操作 。当只存在一个处理器时,实际上只有一个线程 一次执行,但Win32调度程序在它们之间以每秒约18次的速度切换 。
调度程序可以在任何时候停止一个线程运行并启动另一个线程调度是先发制人的 。在挂起一个线程并启动另一个线程之前,操作系统不会等待权限交换机可能随时发生 。由于切换可以在任何两个处理器指令之间发生,因此它可能发生在函数中间的临界点,甚至是执行一个特定程序语句的一半 。
让我们假设两个线程正在单处理器机器(X和Y)上执行示例代码 。在一个很好的情况下,程序可能正在运行,并且调度操作可能会错过这个临界点,给出预期结果:A增加2 。但是,这绝不是保证,而是盲目的机会如果共享变量碰巧是一个指针,那结果可能会让人崩溃 。
说了一大堆理论,下面以代码的方式来看看上述的情况会不会出现,为了便于观查我没有使用视频中案例,而是采用了控制台应用
usesSystem.SysUtils, System.Classes;typeTWorkThread = class(TThread)protectedprocedure Execute; override;end;var// 定义全局变量,充当共享数据Num: Integer = 0;{ TWorkThread }procedure TWorkThread.Execute;begin// 循环的方式自增Numwhile True do begin//为了效果更为明显加入了延时TThread.Sleep(100);// 当Num的值大于10则终止线程if (Num > 10) thenExit;Writeln(Num);Inc(Num);end;end;begin//启动3个线程TWorkThread.Create(False);TWorkThread.Create(False);TWorkThread.Create(False);Readln;end.执行结果如下


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: