首页
社区
课程
招聘
[求助]还是换个标题吧delphi中多线程并发访问无锁队列怎么实现
发表于: 2013-6-7 12:25 7682

[求助]还是换个标题吧delphi中多线程并发访问无锁队列怎么实现

2013-6-7 12:25
7682
http://bbs.pediy.com/showthread.php?t=173091
这个话题我问了下 大概有一个思路就是
采用一种多线程并发访问无锁队列可以实现
但是不知道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里面怎么定义这个东西多线程并发访问无锁队列

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
2
郁闷死了
找了队列的代码整合原先的代码修改了一下 还是出错
看来还是发代码上来 到底什么地方的问题
有想研究的自己去看下,顺便帮我看看怎么会出错
我无奈死了。
搞了四五天,诶。
密码:
kanxue
上传的附件:
2013-6-7 14:43
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
3
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.


这个是代码 我的编译老是提示莫名奇妙的错误
郁闷死了
2013-6-7 14:47
0
雪    币: 602
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
代码混乱,逻辑更乱
2013-6-7 14:55
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
5
帮忙看看 谢谢
2013-6-7 15:11
0
雪    币: 602
活跃值: (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
要是一两句话的事也就帮忙了,这个也不是多难的事情,关键是有些东西你还没理解透,自己找一下资料吧,其实还是很多的
2013-6-7 15:42
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
7
网络上delphi 队列的资料真是凤毛鳞角。我查了基本上都没详细一点的东西
你有空就帮忙看看吧 关键其实就那几句 初始化 push pop 什么的
2013-6-7 16:08
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
8
看来数据结构这个还是有点意思,之前就没想到这么麻烦,现在郁闷了
2013-6-7 17:44
0
雪    币: 6092
活跃值: (744)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
9
已经搞定了 而且方法超级简单  郁闷啊
2013-6-7 22:44
0
游客
登录 | 注册 方可回帖
返回
//