有一天,我正在忙于一个咨询项目,忽然碰到了一个以前从未碰到过的线程同步问题。该公司正在创 建一个 Web 服务,并且服务器收到的客户端请求几乎均需要以只读方式存取某些共享数据。 有时,还会 收到需要修改共享数据的请求,同时我们需要使这些数据保持同步。这种情况听起来非常适合采用读写锁
然而,经过对项目的更深入研究,我了解到该公司的要求有一个不寻常的地方:当服务器接收到 Web 服务请求并且锁的状态为写时,该锁持续极长的一段时间。而当写线程修改共享数据时,要读这些数据的 其他 Web 服务请求需要进入服务器。这里的问题是池中的线程正在被唤醒以处理读请求,但是由于要等 待写线程完成其任务,因而所有读线程会很快转入休眠状态。
创建成百上千的池线程没有花费很 长的时间,并且所有这些线程在操作系统内核内部都处于等待状态。此时许多线程都无法运行,而只是白 白浪费资源(如每个线程的堆栈以及关联的线程内核对象)。这很糟糕。而且越来越糟!当写线程完成共 享数据的写操作时,它会解锁。然后锁看到有成百上千的读线程在等待着它,它便释放所有处于等待状态 的读线程。服务器计算机有四个 CPU,并且这四个小 CPU 必须处理所有这些可运行的线程的工作。 Windows 会使用其正常的轮询调度技术来调度所有这些线程,但将 CPU 不断地从一个线程切换到另 一个线程的开销会大大降低性能、可伸缩性和吞吐量。
这一问题困扰了我好几个月,直到最后我 设计了我自己的线程同步锁 ReaderWriterGate,这一问题才得到解决。该锁非常高效,并且可以非常好 地用于多种应用程序中。ReaderWriterGate 的有趣之处在于调用线程几乎从不中断,即使中断了,也能 保证它们只中断极短的一段时间。而且在内部,由于 ReaderWriterGate 使用的是我的 ResourceLock 派 生类之一(前面提到的 6 月的那个专栏中对此进行了讨论),我只更改一行代码即可让 ReaderWriterGate 在内部使用旋转锁,从而在 Windows 内核中,线程从不中断(我在 2005 年 10 月的 “并发事件”专栏中对此进行了介绍)。这样可以提高性能,不过为了公平起见,它会要求使 用 ReaderWriterGate 的所有线程都具有相同的线程优先级并禁用优先级提升功能。这将进一步提高性能 。此外,ReaderWriterGate 只使用少数几个线程便能够完成非常多的工作。因此,不管向该 Gate 发 出多少请求,所需的资源都非常少。
我用我自己的方法实现了这一功能,并将其作为 Power Threading 库的一部分免费提供,读者可从 www.wintellect.com 下载。如果您要利用我的实现方法,请 遵守该库附带的《最终用户许可协议》(EULA)。更多详细信息请参阅 EULA。
接下来我将对 ReaderWriterGate 背后的原理进行介绍,探讨一种可能的方法,并提供一种研究线程处理和线程同步的 新方式。我希望您能够看到在您的现有代码中可以应用此类思路的地方,从而尽可能少地重新设计架构, 您可以结合其中的某些理念,提高应用程序的性能和可伸缩性。
ReaderWriterGate 对象模型
要使用 ReaderWriterGate 类,只需了解以下几个方法:
public sealed class ReaderWriterGate { public ReaderWriterGate(); public void QueueWrite( ReaderWriterGateCallback callback, Object state); public void QueueRead( ReaderWriterGateCallback callback, Object state); ... // Some methods not shown to simplify the discussion }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数据
, 线程
, 性能
, 同步
, 状态
一个
sreader writer uoml、reader writer uoml、readerwriteruoml.rar、java reader writer、reader writer,以便于您获取更多的相关知识。