【问题标题】:Critical Section in main thread主线程中的关键部分
【发布时间】:2013-01-30 10:12:23
【问题描述】:

我正在开发一个简单的多线程网络爬虫。我正在使用 sqlite 数据库来存储将被扫描的 url。我只有一个数据库句柄问题是主线程查询数据库以产生新线程。线程正在访问相同的句柄,但主线程也。

我已经为每个线程定义了临界区,包括主线程。但是即使线程也处于临界区,主线程也会继续执行代码。

这是一些代码:

  CreateDb;

  InitializeCriticalSection(critical);

  index := 0;

  repeat
   if threads < THREADS_MAX then
   begin
     EnterCriticalSection(critical);
     try
       sqldb.query('SELECT * FROM urls WHERE vizitat=0 AND id>' + IntToStr(index));
       urlcount:= sqldb.rowcount;

       for i:= 1 to urlcount do
       begin
         WriteLn(sqldb.Fs('adresa'));
         sqldb.next;
         index := sqldb.Fi('id');
         with TPageCrawl.Create(@threads,sqldb.Fs('adresa'),index,sqldb) do;
         if threads = THREADS_MAX then break;
       end;
       LeaveCriticalSection(critical);
     except
       LeaveCriticalSection(critical);
       Continue;
     end;
   end;

   Write(logo);
   Sleep(1000);
  until (threads = 0) and (urlcount  < 1);

【问题讨论】:

    标签: multithreading delphi


    【解决方案1】:

    我已经为每个线程定义了临界区

    它们都必须使用相同的临界区才能正确锁定。如果它们都有自己的临界区,那么锁只适用于它们自己。

    我假设你的线程在TPageCrawl,你可以在调用中传入临界区:

    TPageCrawl.Create(critical,@threads,sqldb.Fs('adresa'),index,sqldb)
    

    然后在您的线程进程中,您可以根据需要EnterCriticalSection()LeaveCriticalSection()

    【讨论】:

    • 请注意,这些 API 调用已为您封装在 TCriticalSection 类中,这使得使用它们更容易一些。还有TMultiReadExclusiveWriteSynchronizer 可以满足更复杂的需求。
    • 我正在使用免费的 pascal 我需要一个跨平台的解决方案,所以这工作正常。再次感谢
    【解决方案2】:

    我已经为每个线程定义了临界区,包括主线程。

    这不是它的工作原理。您需要有一个共享的临界区对象。每个线程必须使用相同的临界区才能使序列化工作。您需要在关键部分对象和需要保护的资源之间建立一对一的关系。

    来自documentation

    一个临界区对象一次只能由一个线程拥有,这对于保护共享资源不被同时访问非常有用。

    【讨论】:

    • 愚蠢的部分是我使用共享临界区编写代码但收到访问冲突并指责共享临界区。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多