换个标题吧--delphi多线程并发访问无锁队列怎么实现

bbc9527 2013-06-07 12:42:45
http://bbs.csdn.net/topics/390482498
这个帖子 已经大致的说明了问题
经过几天的思考和奋战
我找到了一个可行的解决方法
多线程并发访问无锁队列
但是不知道在delphi里面 怎么实现
代码可以参考里面的代码
流程我大概的重写一下
创建线程A
1、从队列中获得的M(第一次为0,后面为线程B中获得)
2、判断(线程B是否启动)
3、没有启动 则启动线程B
4、执行动作A(M) ----消费这个数据消费完之后才允许它改变
5、执行动作B(inc(事物C)) 消费
6、回到1 直到线程A退出
创建线程B
1、判断是否存在(事物C)
2、不存在则创建(事物C) 生产
3、M=得到变量(事物C)----------- 不断生产这个 数据 并且给A进程消费把这次产生的数据M存到队列里面
4、执行动作B(inc(事物C)) 消费
5、回到1 直到线程B退出
这样的话只要解决队列的问题就可以解决之前的数据覆盖和等待的问题
但是。。delphi里面怎么定义这个东西多线程并发访问无锁队列
论坛貌似不方便发代码 这个地方可以下代码
http://bbs.pediy.com/showthread.php?t=173091
...全文
348 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
bbc9527 2013-06-08
  • 打赏
  • 举报
回复
已经搞定不用这么麻烦 简单就可以解决了
sololie 2013-06-07
  • 打赏
  • 举报
回复
伤脑筋,撸过一顶
bbc9527 2013-06-07
  • 打赏
  • 举报
回复
http://bbs.pediy.com/showthread.php?p=1185887#post1185887 帮忙看下代码 有什么问题谢谢了 这个是文件地址
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
 const
   ceshi=10;
type
  TForm1 = class(TForm)
    btn1: TButton;
    btn2: TButton;
    mmo1: TMemo;
    mmo2: TMemo;
    btn3: TButton;
    btn4: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  //缓冲区对象,包含同步句柄和缓冲区
  PDb = ^TDb;
  TDB = class
  private
    FCap: integer;
    Flist: TList;
    FSycHandle: Thandle;
  public
    constructor Create(const pCap: Integer);overload;
  public
    FItemCount: integer;                                                        //测试适用
    destructor Destroy; override;
    function IsEmpty: Boolean;
    function IsFULL: Boolean;
    function Pop: Pointer;
    procedure Push(const pObect: pointer);
    property SycHandle: Thandle read FSycHandle;
  end;
type
  TDBB = class
  private
    //读取缓冲区临界区
    //FPopCritical: TRTLCriticalSection;
    //写入缓冲区临界区
    //FPushCritical: TRTLCriticalSection;
    FBufferA: TDB;
    FbufferB: TDB;
    FPushA: PDB;
    FPushB: PDB;
    FPopA: PDB;
    FPopB: PDB;
    function ChangeBuffer(const pQueueBuffer: PDb): pDb;

  public
    constructor Create(const pCap: Integer);overload;
    destructor Destroy; override;
    function Popup: Pointer;
    function Push(const pObject: pointer): Boolean;
    //
    procedure Flush;
    //获得缓冲区元素数
    function GetALLCount: Integer;
    //缓冲区是否为空
    function ISEmpty: Boolean;

  end;
type 
  Tshiwu=packed record
    c:Integer;
    m:Integer;
    end;
type
  Tthread3 = class(Tthread)
  protected
  procedure Execute;override;
  end;


 
type
  Tthread5 = class(Tthread)
  protected
  procedure Execute;override;
   end;

var
  Form1: TForm1;
  bcunzai:Boolean;
  astopnow:Boolean;
  autoattnow:Boolean;
  xiaofeione:Tthread3;
  xiaofeitwo:Tthread5;
  shiwuc:Tshiwu;
  dq:TDBB;
implementation

{$R *.dfm}
constructor TDB.Create(const pCap: Integer);
begin
  inherited create;
  FCap := pCap;
  FItemCount := 0;
  FSycHandle := CreateEvent(nil, false, false, nil);
  Flist := TList.Create;
end;

destructor TDB.Destroy;
begin
  Flist.Clear;
  Flist.Free;
  CloseHandle(FSycHandle);
  inherited;
end;

function TDB.IsEmpty: Boolean;
begin
  Result := Flist.Count = 0;
end;

function TDB.IsFULL: Boolean;
begin
  Result := Flist.count >= FCap;
  if result then
  begin
    FItemCount := 10;
  end;
end;

function TDB.Pop: Pointer;
begin
  if Flist.Count = 0 then
  begin
    result := nil;
    exit;
  end;
  Result := Flist.Items[0];
  Flist.Delete(0);
  dec(FItemCount);
end;

procedure TDB.Push(const pObect: pointer);
begin
  Flist.Add(pObect);
  inc(FItemCount)
end;

constructor TDBB.Create(const pCap: Integer);
begin
  inherited Create;
  FBufferA := TDB.Create(pCap);
  FBufferB := TDB.Create(pCap);
  FPushA := @FBufferA;
  FPushB := @FbufferB;
  FPopA := @FBufferA;
  FPopB := @FbufferB;
  //InitializeCriticalSection(FPopCritical);
  //InitializeCriticalSection(FPushCritical);
end;

function TDBB.Popup: Pointer;
begin
  //EnterCriticalSection(FPopCritical);
  //try
  if FPopA.IsEmpty then
  begin
    //释放当前读取缓冲区
    SetEvent(FPopA.SycHandle);
    //form1.mmo1.Lines.Add('通知  ::' + inttostr(integer(FPopA)) + ':' + inttostr(FPopA.SycHandle));
    // 得到当前读取缓冲区
    FPopB := ChangeBuffer(FPopA);
    //form1.mmo1.Lines.Add('Pop  ::' + inttostr(integer(FPopB)) + ':' + inttostr(FPopB.SycHandle));
    //接管当前读取缓冲区的拥有权
    WaitForSingleObject(FPopB.SycHandle, INFINITE);
    // 接管读取缓冲区
    FPopA := FPopB;
  end;
  result := FPopA.Pop;
  //finally
  //  LeaveCriticalSection(FPopCritical);
  //end;
end;

function TDBB.Push(const pObject: pointer): Boolean;

begin
  //EnterCriticalSection(FPushCritical);
  //try
  if FPushB.IsFULL then
  begin
    //释放当前写入缓冲区
    SetEvent(FPushB.SycHandle);
    //form1.Memo1.Lines.Add('通知 ::' + inttostr(integer(FPushb)) + ':' + inttostr(FPushb.SycHandle));
    //得到当前写入取缓冲区
    FPushA := ChangeBuffer(FPushB);
    //form1.Memo1.Lines.Add('Push ::' + inttostr(integer(FPusha)) + ':' + inttostr(FPusha.SycHandle));
    //接管当前写入缓冲区的拥有权
    WaitForSingleObject(FPushA.SycHandle, INFINITE);
    //接管写入缓冲区
    FPushB := FPushA;
  end;
  FPushB.Push(pObject);
  result := true;
  //finally
  //  LeaveCriticalSection(FPushCritical);
  //end;
end;

destructor TDBB.Destroy;
begin
  FBufferA.Free;
  FBufferB.Free;
  //DeleteCriticalSection(FPopCritical);
  //DeleteCriticalSection(FPushCritical);
  inherited;
end;

function TDBB.ChangeBuffer(const pQueueBuffer: PDb): pDb;
begin
  if pQueueBuffer = @FBufferA then
  begin
    result := @FBufferB;
  end;
  if pQueueBuffer = @FBufferB then
  begin
    result := @FBufferA;
  end;
end;

procedure TDBB.Flush;
begin
  SetEvent(FBufferA.SycHandle);
  SetEvent(FBufferB.SycHandle);
end;

function TDBB.GetALLCount: Integer;
begin
  Result := FBufferA.FItemCount + FBufferA.FItemCount;
end;

function TDBB.ISEmpty: Boolean;
begin
  Result := FBufferA.IsEmpty and FBufferB.IsEmpty;
end;


procedure eat(var shiwucm:integer);
//var
  begin
    Randomize;
    if shiwucm=0 then
    begin
       shiwucm:=0;
       Form1.mmo1.lines.add('事物m被消费:目前剩余'+inttostr(shiwucm));
    end else
    begin
       shiwucm:=shiwucm-random(10);
       Form1.mmo1.lines.add('事物m被消费:目前剩余'+inttostr(shiwucm));
       if (shiwucm<0) or (shiwucm=0)then
       begin
          shiwucm:=0;
        Form1.mmo1.lines.add('事物m被消费:目前剩余0');
       end;
    end;


  end;

procedure jianshao(var shiwucc:integer);
//var
  begin
    Randomize;
    if shiwucc=0 then
    begin
       shiwucc:=0;
    end else
    begin
       shiwucc:=shiwucc-random(10)-15;
       Form1.mmo2.lines.add('事物c被消费:目前剩余'+inttostr(shiwucc));
       if (shiwucc<0) or (shiwucc=0)then
       begin
          shiwucc:=0;
          Form1.mmo2.lines.add('事物c被消费:目前剩余0');
       end;
    end;


  end;

procedure Tthread3.Execute;

begin

  

 //repeat

    //dq.Create();

 repeat
      if (shiwuc.m<>0)then
      begin
      eat(shiwuc.m);  //消费物品一
      end else
      begin
        if dq.ISEmpty()=False then    //这里判断队列是否为空
        begin
        shiwuc.m:=integer(dq.Popup()); //这里清理队列
        end;


      end;
     if bcunzai=false then
     begin
      xiaofeitwo:=Tthread5.Create(False);
     end;


      Sleep(50);



      jianshao(shiwuc.c);



  
   Sleep(400);
 until astopnow=False;//

  //  dq.Destroy;
  //end;
end;


procedure Tthread5.Execute;

begin
       bcunzai:=True;
       autoattnow:=true;
       Randomize;

       repeat
       Sleep(150);
      // shiwuctwo:=quanjushiwuc;
       if  shiwuc.c=0 then  //这里C消费消费完毕之后 重新生产 但是会产生冲突 如果两个都消费完就没冲突 如果两个都消费完这样无效率
       begin
          shiwuc.m:=50+random(50);
          shiwuc.c:=430+random(30);
          dq.Push(@shiwuc.m);  //这里把数据加入队列
          Form1.mmo2.lines.add('事物m产生:'+inttostr(shiwuc.m));
          Form1.mmo2.lines.add('事物c产生:'+inttostr(shiwuc.c));
       end;

       jianshao(shiwuc.c);
        Sleep(300);
      until autoattnow=False;


end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 bcunzai:=False;
 astopnow:=true;
shiwuc.m:=0;
shiwuc.c:=0;
 autoattnow:=False;
 //dq.Create();
 
end;


procedure TForm1.btn3Click(Sender: TObject);
begin
    astopnow:=False;
    xiaofeione.Suspend;
    xiaofeione.DoTerminate;
   // dq.Destroy;
end;

procedure TForm1.btn1Click(Sender: TObject);
begin

  xiaofeione:=Tthread3.Create(False);
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  xiaofeitwo:=Tthread5.Create(False);
end;

procedure TForm1.btn4Click(Sender: TObject);
begin
   autoattnow:=False;
   xiaofeitwo.Suspend;
   xiaofeitwo.DoTerminate;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  //dq.Destroy;
end;

end.
这个是代码 pas 的 好心的帮看下
yunsuifeng2009 2013-06-07
  • 打赏
  • 举报
回复
我是来帮楼主顶贴的。我还没有用到这个邮件,但是以后应该会用到。

16,749

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧