您现在的位置:首页 >> 基础算法 >> window基础 >> 内容

Delphi中多线程安全和并发问题(2)

时间:2011/9/3 15:36:58 点击:

Atomic操作

  有一种方法是说如果操作是Atomic,资源不要被保护。Atomic操作是这样一种操作,它太小了以至于不能被计算机处理器分划开来。因为它尺寸小,从而它不会受到Contentiion的影响因为它将由自身执行而且在执行过程中不会有Task的切换。一般情况下,Atomic操作是被编译为一条汇编指令的源代码。

  典型的任务诸如读取或者写入一个整型或者布尔型变量被认为是Atomic操作,因为它们被编译为一条Move指令。然而我推荐你绝对不要依赖原子操作,因为某些情况下甚至写入一个整型或者布尔型变量都能包括多于一个的动作,这要看数据首先是从哪儿读来的。此外,这还依赖于编译器内部的奥秘,而这可能会在不告知你的情况下做出改变。依赖源代码级的Atomic操作将产生未来会有问题的代码而且可能在多处理器的机器或者别的操作系统上行为非常不同。

  我曾经见过一个铁打不动的Atomic操作。然而一个非常prominent的未来事件证明了我的观点,那就是.net。你的代码首先编译为IL,然而再编译为机器码,可能还是在不同厂商的不同平台上,你还能确信你的代码最终还是Atomic操作吗?

  选择最终还是要看你自己,当然有许多声音围绕着对Atomic操作的偏爱和反对。在大部分情况下,依赖原子操作仅仅节省了几毫秒,以及几字节的代码。我强烈推荐不要去使用Atomic操作,因为它们带来的好处如此至少而liabilities如此之巨大。把所有操作都当作非Atomic操作来对待。

  操作系统的支持

  许多操作系统对非常基本的线程安全的操作提供了支持。

  Windows支持一套称为Interlocked Function的函数。这些函数的用处非常有限,而且仅仅包括简单的对整数的操作,诸如步增,步减,加,Swap以及Swap-Compare。

  函数的数目和Windows的版本有关,而且可能在低版本的Windows上发生死锁。在大部分应用程序中,它们提供的性能上的好处非常少。

  因为综合这些,用处有限,不断变化的支持,可怜的性能优势因素,建议你用Indy的线程安全的同等物来替代。

  Windows还包括对特殊的IPC(进程间通信)对象的支持,这些对象在Delphi有经过包装的类。这些对象和IPC一样对线程操作极端有用。

  显式保护

  显式保护包括每个Task都知道一个资源受到了保护而且在访问这个资源之前采取了显式的防御步骤。一般这样的代码式在被多个Task并发执行的函数之中,或者被封装到了一个被许多不同位置调用的函数之中作为一个线程安全的封装。

  显示保护一般要利用资源保护对象。简单来说,资源保护对象把对资源的访问限制为了一次一Task。资源保护对象并没有实际限制对资源的访问,如果它做到了,它可能必须要知道每一个和所有的资源类型的细节。它就像红绿灯,而代码要遵守它并给它提供输入。每个资源保护对象用不同的机理,不同的输入,以及不同程度的额外负担实现了不同种类的红绿灯。这使得能够选择不同的资源保护对象来更好的适应不同类型的资源以及不同的场合。

  资源保护对象以不同形式存在,下面就来逐个介绍。

  Critical Section

  Critical Section可以用来控制对全局资源的访问。Critical Section是轻量级的并且在VCL中实现于TCriticalSection之中。简单来说,Critical Section使得多线程程序中的一个线程能够暂时阻塞所有其他线程尝试使用同一个Critical Section。Critical Section就像红绿灯,只当前面的路没有任何车辆时才变绿。Critical Section可以用来确保一次只有一个线程正在执行那一块代码。因此,受到Critical Section保护的那块代码应当尽可能的小因为如果使用不当的话它们可能严重影响性能。所以,每块代码都应当使用它们自己的TCriticalSection,而不是重用全程序共享的TCriticalSection。

  要进入Critical Section,使用Enter方法,而Leave方法是用来退出Critical Section的。TCriticalSection还分别有Acquire和Release方法来做与Enter和Leave完全一样的事情。

  假设有一个服务器需要记录有关登陆了的客户端的信息,并且要在主线程中显示这些信息。一个可能的选择是使用Synchronize。然而使用这个方法在同时有许多客户登陆时会对连接线程产生性能上的负面影响。取决于服务器的需要,一个更好的选项可能是记录下信息并且让主线程用Timer来读取这些信息。下面的代码是一个使用了Critical Section的这种技术的例子。

上一页12345下一页

作者:网络 来源:转载
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 盒子文章(www.2ccc.com) © 2024 版权所有 All Rights Reserved.
  • 沪ICP备05001939号