1

我正在开发一个简单的多线程网络爬虫。我正在使用 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);
4

2 回答 2

6

我为每个线程定义了关键部分

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

我假设您的线程在 中TPageCrawl,您可以在调用中传递关键部分:

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

然后在你的线程过程中EnterCriticalSection(),你可以LeaveCriticalSection()根据需要。

于 2013-01-30T10:14:32.457 回答
4

我已经为每个线程定义了关键部分,包括主线程。

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

文档中:

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

于 2013-01-30T10:14:45.680 回答