delphi多线程加锁

前几日,调试一BUG,过程先不说,最后调试到MM,即Debug dcu,然后进入到GetMem.inc中的Get/FreeMem函数处后,出现AV。

然后一通找。。。郁闷了N天,后来发现将MM切换到QMM后,一切正常,然后再切回原MM,BUG出现。。。

按经验,此类问题一般由于线程未有锁保护引起,但就是没找到原因所在。

好吧,也不怎么滴,突然想起IsMultiThread变量,想起MM的Get/Free/Realloc都需要这个玩意进行保护,而VCL中,只有一个地方对这变量进行操作: Classes.TThread.Create->System.BeginThread

然后才想起自己未使用TThread,使用API.CreateThread进行创建线程,而它未对IsMultiThread进行置true操作,问题找到,BUG解除。

遂,本文记录此问题。

BUG形成:

1:程序未使用TThread或BeginThread进行创建线程,这样,它就不会对IsMultiThread进行操作

2:自行使用API.Windows.CreateThread创建线程,且未对IsMultiThread置true

3:在创建的线程中,进行Get/Free/ReallocMem,并与其它线程(如主线程)进行交互该内存块

BUG展现:

1:该BUG将会引起MM数据结构错误,问题就大了去。

出现AV时,watch查看的数据是错误的,且随机的给你不一样的数据

call stack也傻了,定位到无边际的代码。。。

总之,一切都傻掉了,不可信了。

BUG避免:

1:慎用API.Windows.CreateThread,如果要对它操作,请记得IsMultiThread := True;

如果不记得,请参照代码: System.BeginThread

或者直接使用System.BeginThread进行创建线程。

2:使用QMM,QMM是自动维护IsMultiThread,有线程数N(N>1)时, IsMultiThread=true, N=1时, IsMultiThread = false;

这点,其它MM,俺所查看的,都未做处理。(偶在打广告哩)

个人建议是:开发环境必备两套以上MM,以作备用,遇到一些莫名问题,切换一下,用以确认是否MM问题引起。

注:

  线程加锁:在end.上面加上
  initialization
  IsMultiThread := True;

  MM=Memory Manager, D2005版本开始集成FastMM。

  不过,从D7(D5没注意看,应该也是)的GetMem.Inc,一直到FastMM4.991都依赖于IsMultiThread标志进行线程保护,未进行自维护该标志。

所以,当出现此BUG条件形成时,就会出现:我知道因为多线程未保护引起数据错乱而引起的BUG,但就是找不着在哪里触发的,怎么去解决。这才是最坑爹的。 :)

时间: 2024-10-13 02:08:07

delphi多线程加锁的相关文章

delphi 多线程

CoInitialize(nil); //调用COM,需要初始化 HThread: THandle; ID: DWord; HThread:= CreateThread(nil, 0, @start, nil, 0, ID); ResumeThread(HThread_1); //返回值为1,继续线程 SuspendThread(HThread_1); //挂起线程 //写入INI配置,决定是否暂停线程while True do begin cap:= IniFile.ReadString('U

简单类型多线程加锁

下表是一个多线程加锁的规律表   操作的结果与初值无关 操作的结果与初值相关 写简单数据类型 不需要加锁① 需要加锁② 写复杂数据类型 需要加锁③ 需要加锁④ 读简单数据类型 不需要加锁⑤ 不需要加锁⑥ 读复杂数据类型 需要加锁⑦ 需要加锁⑧

转:学习笔记:delphi多线程学识

学习笔记:delphi多线程知识 最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处. Delphi的线程同步方法: 1.临界区 申明一个临界资源 FLock : TRTLCriticalSection; 先初化一个临界资源对象 InitializeCriticalSection(FLock) 销毁临界资源对象 DeleteCriticalSection(FLock) proced

delphi 多线程 动态创建ADO

delphi 在多线程中动态连接ADO控件 异常:exception class EOleSysError with message '尚未调用CoInitialize' 如果是使用多线程的话那就在 Execute事件的开头加上 CoInitialize(nil); 结尾加上CoUninitialize() unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Fo

Delphi多线程下的ADO编程

前言: 几个月前接到一个任务:将一后台程序访问数据库的方式从BDE改为ADO,原因是由于业务量的增加,通过BDE不论是向数据库写入数据还是从数据库中读出数据的速度都变得无法忍受,大家都知道ADO在数据库访问速度方面比BDE要快的多了(我写了一个测试程序使用ADO比使用BDE快了近100倍!).这个任务还不简单嘛,只要将BDE的控件更换成ADO的再修改一些代码不就搞定了!我当时确实是这么想的,而且用了不到一个小时就搞定,测试运行一段没问题,大功告成了,我想.谁知道一个恶梦就此开始,我的愚昧无知使我

delphi 多线程2

多线程常用的内核对象:CreateEvent事件,CreateMutex互斥,CreateSemaphore信号,CreateWaitableTimer计时器 {建立事件} function CreateEvent( lpEventAttributes: PSecurityAttributes; {!} bManualReset: BOOL; bInitialState: BOOL; lpName: PWideChar ): THandle; stdcall; {建立互斥} function C

Python多线程编程之多线程加锁

Python语言本身是支持多线程的,不像PHP语言. 下面的例子是多个线程做同一批任务,任务总是有task_num个,每次线程做一个任务(print),做完后继续取任务,直到所有任务完成为止. 1 #coding:utf-8 2 import threading 3 4 start_task = 0 5 task_num = 10000 6 mu = threading.Lock() ###通过工厂方法获取一个新的锁对象 7 8 class MyThread(threading.Thread):

Delphi多线程编程之同步读写全局数据

开始研究最重要的多线程读写全局数据了,结合书上的例子,我修改成下面的情况: unit Tst_Thread3U; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type   TForm1 = class(TForm)     Button1: TButton;     Memo1: TMemo;     Button2: TBu

Delphi多线程编程(8)--多线程同步之CriticalSection(临界区)

转载自:万一的博客 先看一段程序 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1=class(TForm) ListBox1: TListBox; Button1: TButton; procedure FormCreate(Sender: TObject); procedure