我读过线程非常有问题.有哪些替代品?什么能自动处理阻塞和填充?
很多人推荐后台工作者,但我不知道为什么.
有人想解释"简单"的替代方案吗?用户将能够选择要使用的线程数(取决于它们的速度需求和计算机功率).
有任何想法吗?
总结线程的问题:
竞争的一个示例:假设两个线程共享对存储数字的某个内存的访问.线程1从存储器地址读取并将其存储在CPU寄存器中.线程2也是如此.现在,线程1递增数字并将其写回内存.线程2然后做同样的事情.结果:数字只增加1,而两个线程都试图递增它.这种相互作用的结果取决于时间.更糟糕的是,你的代码可能看起来没有错误,但是一旦在蓝色的月亮中,时机是错误的,坏事就会发生.
为了避免这些问题,答案很简单:避免共享可写内存.相反,使用消息传递来在线程之间进行通信.一个极端的例子是将线程放在单独的进程中,并通过TCP/IP连接或命名管道进行通信.
另一种方法是仅共享只读数据结构,这就是函数式编程语言可以在多个线程中很好地工作的原因.
这是一个更高级别的答案,但如果您想考虑线程的其他替代方案,它可能会有用.无论如何,大多数答案都讨论了基于线程(或线程池)或.NET 4.0任务的解决方案,但还有一个替代方案,称为消息传递.这已成功用于Erlang(爱立信使用的功能语言).由于功能编程在这些日子里变得越来越主流(例如F#),我想我可以提一下.在一般情况下:
当你有一些相对长时间运行的计算时,通常可以使用线程(或线程池).当它需要与其他线程共享状态时,它会变得棘手(你必须正确使用锁或其他同步原语).
任务(在.NET 4.0中的TPL中可用)非常轻量级 - 您可以将程序拆分为数千个任务,然后让运行时运行它们(它将使用最佳线程数).如果您可以使用任务而不是线程编写算法,这听起来是个好主意 - 当您使用较小的步骤运行计算时,可以避免某些同步.
声明性方法(.NET 4.0中的PLINQ是一个很好的选择)如果你有一些可以使用LINQ原语编码的更高级别的数据处理操作,那么你可以使用这种技术.运行时会自动并行化的代码,因为LINQ没有规定如何准确地应该评估结果(你刚才说你想要得到什么样的结果).
消息传递允许您将两个写程序作为并发运行的进程执行一些(相对简单的)任务,并通过相互发送消息进行通信.这很好,因为你可以在没有通常的同步问题的情况下共享一些状态(发送消息)(你只需发送消息,然后做其他事情或等待消息).以下是Robert Pickering 对F#中消息传递的一个很好的介绍.
请注意,最后三种技术与函数式编程密切相关 - 在函数式编程中,您以不同的方式设计程序 - 作为返回结果的计算(这使得使用任务更容易).您还经常编写声明性和更高级别的代码(这使得使用声明性方法更容易).
在实际实现方面,F#在核心库中有一个很棒的消息传递库.在C#中,您可以使用并发和协调运行时,它感觉有点"hacky",但也可能非常强大(但可能看起来太复杂).
| 归档时间: |
|
| 查看次数: |
5958 次 |
| 最近记录: |