是否有用于创建没有同步和锁的线程的用例?

时间:2009-11-29 02:10:30

标签: java multithreading synchronization

由于线程执行发生在池中,并且不能保证以任何特定顺序排队,那么为什么要在没有同步和锁保护的情况下创建线程?为了保护附加到对象状态的数据(我理解为使用线程的主要目的),锁定似乎是唯一的选择。如果你不同步,最终你会遇到竞争条件和“损坏”的数据。因此,如果您对保护该数据不感兴趣,那么为什么要使用线程?

7 个答案:

答案 0 :(得分:10)

如果没有共享的可变数据,则不需要同步或锁定。

答案 1 :(得分:9)

代表团,就像一个例子。考虑一个获取连接请求的Web服务器。它可以将特定请求委托给工作线程。主线程可以将所需的所有数据传递给工作线程,只要该数据是不可变的,并且不必担心并发数据访问。

(就此而言,主线程和工作线程都可以将所有不可变数据发送到他们想要的彼此,它只需要某种类型的消息队列,因此队列可能需要同步而不是数据本身。但是你不需要消息队列来获取数据到工作线程,只需在线程启动之前构造数据,并且只要数据在那时是不可变的,您就不需要任何同步或锁定或任何并发管理排序,而不是运行线程的能力。)

答案 2 :(得分:6)

同步和锁定可保护共享状态免受冲突的并发更新的影响。如果没有要保护的共享状态,则可以在不锁定和同步的情况下运行多个线程。这可能是Web服务器中具有多个独立工作线程来处理传入请求的情况。避免同步和锁定的另一种方法是让线程仅在不可变共享状态下运行:如果线程无法更改另一个线程正在运行的任何数据,则并发非同步访问就可以了。

或者您可能正在使用基于Actor的系统来处理并发。参与者只通过消息传递进行通信,没有共享状态让他们担心。所以在这里你可以让很多线程运行很多没有锁的Actors。 Erlang uses this approach,并且有Scala Actors library允许您在JVM上以这种方式编程。此外还有Actors-based libraries for Java

答案 3 :(得分:4)

  

为了保护附加的数据   对象的状态(我的理解   成为使用的主要目的   线程),锁定似乎是   唯一的选择。 ... 因此,如果   你对保护不感兴趣   那个数据,然后为什么要使用线程   所有?

您问题的突出位置是不正确的,因为它是您对线程“怀疑”的根本原因,所以需要明确解决。

实际上,使用线程的主要目的是允许任务尽可能并行进行。在多处理器上,并行性(所有条件都相同)会加速计算。但是,还有其他好处也适用于单处理器。最明显的一点是,线程允许应用程序在等待某些IO操作完成时继续工作。

线程实际上并没有以任何有意义的方式保护对象状态。您对线程的保护来自:

  • 声明具有正确访问权限的成员
  • 隐藏getter / setter背后的状态,
  • 正确使用同步,
  • 使用Java安全框架和/或
  • 向其他服务器/服务发送请求。

您可以独立于线程执行所有这些操作。

答案 4 :(得分:3)

java.util.concurrent.atomic提供了一些可以无锁且线程安全的方式执行的最小操作。如果您可以完全围绕这些类和操作安排并发性,那么您的性能可以大大提高(因为您可以避免与锁定相关的所有开销)。当然,处理这样一个可以简化的问题是很不寻常的(通常需要一些锁定),但是,如果你确实发现自己处于这种情况,那么,那就是你要问的用例! - )

答案 5 :(得分:2)

对共享数据还有其他类型的保护。也许你有原子部分,监视器,软件事务内存或无锁数据结构。所有这些想法都支持并行执行而无需显式锁定您可以使用Google中的任何一个术语来学习有趣的内容。如果您的主要兴趣是Java,请查看Tim Harris的工作。

答案 6 :(得分:1)

线程允许多个并行工作单元同时进行。同步只是为了保护分片资源免受不安全访问,如果不需要你不使用它。

当访问某些资源(例如IO)时,线程上的处理会延迟,并且可能需要让CPU处理其他工作单元,而其他工作单元则会延迟。

在另一个答案的例子中,听取服务请求可能是一个独立于响应请求的工作单元,因为后者是由于资源争用导致的阻塞 - 比如访问磁盘或IO。