Delphi中的TList在多线程中的应用

6

在一个多线程应用程序中,如果只有一个线程写入TList,其他所有线程都可以访问它,那么使用TList是否安全?

每个线程都拥有一个唯一的TList,只有该线程才会向其中写入数据,而其他线程将仅访问它以获取数据。

这样做是安全的吗?

2个回答

11

如果没有同步,这不是安全的。读取线程可能会在写线程修改列表时处于读取的中间状态。而修改列表可能意味着重新分配基础内存。

RTL为这种情况提供了TThreadList类。每个线程(包括写和读线程)都需要将对列表的所有访问包装在LockListUnlockList对中。

var
  ThreadList: TThreadList;//declared in some shared location
....
//each thread accesses the list like this:
var
  List: TList;
....
List := ThreadList.LockList;
try
  .... do stuff with List
finally
  ThreadList.UnlockList;
end;

如果您正在使用支持泛型的Delphi,那么有一个泛型版本TThreadList<T>


嗯,我从没想到过这点,我以为只有一个线程写入的话就比较安全了,但没有想到你刚刚解决的问题。那么我应该使用TThreadList。谢谢。 - Junaid Noor
1
我将使用Indy的TIdThreadSafeList,只是试图以某种方式跳过锁定和解锁的想法。服务器中有许多线程安全列表,并且为每个操作锁定每个列表可能会耗费太多时间,因为该操作很可能会发生太多次。 - Junaid Noor
这可能会引起很多争议,因为在任何给定时间只有一个线程可以访问列表。根据列表中存储的数据类型,如果编写者不删除项目,则优化的好方法是编写读取器以锁定列表以仅复制内容,然后解锁并对副本执行其工作。在其他情况下,您还可以考虑使用多个读取器-单个编写器方法。 - jachguate
是的,这就是我认为应该做的,我锁定列表并将其分配给一个简单的TList,解锁线程安全列表,然后在普通TList上执行操作。 - Junaid Noor
2
如果写入线程销毁了项目并且您已经复制了引用,则无法正常工作。 - David Heffernan

5

如其他人所述,TList本身不是线程安全的。如果你担心使用TThreadList会带来性能开销(它在内部使用了临界区),那么可以尝试使用TMultiReadSingleWriteSynchronizer或者Win32SRW锁来封装现有的TList代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接