我一直在考虑在我的应用程序中添加线程处理以加快执行速度,但问题是我实在不知道如何使用线程,或者什么被认为是“线程安全”的。例如,游戏引擎如何在其渲染过程中利用线程,或者在什么情况下线程只会被视为阻碍?有人可以指引我一些资源来帮助我学习更多,或者在这里解释一下吗?
我一直在考虑在我的应用程序中添加线程处理以加快执行速度,但问题是我实在不知道如何使用线程,或者什么被认为是“线程安全”的。例如,游戏引擎如何在其渲染过程中利用线程,或者在什么情况下线程只会被视为阻碍?有人可以指引我一些资源来帮助我学习更多,或者在这里解释一下吗?
这是一个非常广泛的话题。但如果我对线程一无所知,以下是我想了解的内容:
它们是单个进程内的执行单位,发生“并行” - 这意味着处理器中当前执行单位会快速切换。可以通过不同的方式实现。切换被称为“上下文切换”,与此相关的有一些开销。
它们可以共享内存!这就是问题可能发生的地方。我将在稍后的要点中更深入地讨论此事。
并行化应用程序的好处在于使用计算机的不同部分的逻辑可以同时发生。也就是说,如果您的进程一部分是I/O绑定,另一部分是CPU绑定,那么I/O密集操作不必等待CPU密集操作完成。某些语言还允许您在具有多核处理器的情况下同时运行线程(从而并行化CPU密集型操作),尽管这并不总是成立。
线程安全意味着没有竞争条件,这是一个术语,用于描述当您的进程的执行取决于时间(您不希望依赖于此)时发生的问题。例如,如果您有线程A
和B
都在增加一个共享计数器C
,则可能会出现这种情况:A
读取C
的值,然后B
读取C
的值,然后A
使用C+1
覆盖C
,然后B
再次使用C+1
覆盖C
。请注意,C
只实际增加了一次!
避免竞争条件的一些常见方法包括同步,它排除对共享状态的相互访问,或者根本不具有任何共享状态。但这只是冰山一角 - 线程安全是一个非常广泛的话题。
我希望这能有所帮助!请理解,这只是一个需要很多学习的东西的快速介绍。我建议您找到一些关于您偏爱的编程语言中多线程的资源,并进行深入阅读。
关于线程,有四个需要知道的事情。
线程类似于进程,但它们共享内存。
线程通常具有硬件、操作系统和语言支持,这可能使它们比进程更好。
线程需要支持许多琐碎的小事情(如锁和信号量),以便不会将它们共享的内存置于不一致状态。这使得它们有点难以使用。
锁定不是自动的(在我所知道的语言中),因此您必须非常小心地处理它们(隐式)共享的内存。
线程不能加速应用程序。算法可以加速应用程序。如果适当,线程可以在算法中使用。
好的,也许有人能更好地回答这个问题,但是线程的目的是进行后台处理,而不会冻结用户界面。您不想停止接受键盘输入或鼠标输入,并告诉用户:“稍等片刻,我想完成这个计算,只需要几秒钟。”(商业程序经常这样做还是令人惊讶的。
就线程安全而言,它意味着一个函数没有一些内部保存的状态。如果有的话,您无法同时使用多个线程。
至于线程编程,你只需要开始做,然后你就会遇到各种独特的线程编程问题,例如对数据的同步访问,在这种情况下,你必须决定使用一些同步方法,如临界区或互斥体或其他一些方法,每一种方法的行为略有不同。
至于进程和线程之间的差异(您没有提问),进程是操作系统级别的实体,而线程与程序相关联。在某些情况下,您的程序可能希望创建一个进程而不是一个线程。
线程只是同时执行多个任务的一种方式(假设运行它们的平台支持并行执行)。线程安全只是确保线程不会以有害的方式相互影响的简单方法(好吧,实际上与线程有关的事情没有什么是真正简单的)。
通常情况下,由于可能出现多种性能问题和复杂性问题,您不太可能看到系统使用多个线程来渲染屏幕上的图形。但是,与状态管理(或人工智能)相关的其他任务可以潜在地移动到单独的线程中。
线程编程的第一条规则:不要使用线程。第二条规则:如果你必须违反第一条规则……还是不要使用线程。第三条规则:好吧,你必须使用线程,那么在继续之前,先了解线程陷阱、锁定以及常见的线程问题,如死锁和活锁。
要明白,线程并不能加速任何事情,它只有在后台运行长时间进程时才有用,让用户可以在应用程序中做其他事情。如果你必须允许用户与应用程序交互,同时应用程序在后台执行其他任务,比如轮询套接字或等待来自应用程序其他地方的异步输入,那么你确实需要使用线程。
Effective Java 和 Clean Code 中的线程部分都是线程及其陷阱的良好介绍。
既然这个问题被标记为“Java”,我假设您熟悉Java,那么这是一个很好的入门教程http://java.sun.com/docs/books/tutorial/essential/concurrency/
Orm,这是一个很好的问题。我认为所有认真的程序员都应该学习线程,因为最终你将会至少考虑使用它们,当发生这种情况时,你真的希望做好准备。并发错误可能非常微妙,避免它们的最佳方法是了解哪些惯用语是安全的(-ish)。
我强烈建议您花时间阅读Doug Lea的书《Java并发编程实战》:
http://gee.cs.oswego.edu/dl/cpj/Lea不仅花时间教授概念,还向您展示如何正确和不正确地使用并发编程原语(在Java中,但对于任何其他使用共享内存锁定/信号样式并发的环境也有帮助)。最重要的是,他教授了对并发编程难度的尊重。
我应该补充说,这种并发编程风格是最常见的,但不是唯一的方法。还有消息传递,它更安全,但需要您以不同的方式构建算法。
有一本不错的书,Java并发编程实战,http://www.javaconcurrencyinpractice.com/。