Java避免竞争条件没有同步/锁定

时间:2011-12-01 11:27:07

标签: java multithreading concurrency race-condition synchronized

为了避免竞争条件,我们可以在共享变量上同步write和access方法,将这些变量锁定到其他线程。

我的问题是,是否有其他(更好)的方法来避免竞争条件?锁定使程序变慢。

我发现的是:

  • 使用原子类,如果只有一个共享变量。
  • 对多个共享变量使用不可变容器,并使用volatile声明此容器对象。 (我在“Java Concurrency in Practice”一书中找到了这种方法)

我不确定它们的表现是否比同步方式更快,还有其他更好的方法吗?

感谢

5 个答案:

答案 0 :(得分:6)

避免状态。尽可能使您的应用程序成为无状态。每个线程(操作序列)应该在开头采用上下文并使用此上下文将其从方法传递给方法作为参数。

当此技术无法解决您的所有问题时,请使用事件驱动机制。当您的代码必须与其他组件共享某些内容时,它会将事件(消息)抛出到某种总线(主题,队列,等等)。组件可以注册侦听器以侦听事件并做出适当的反应。在这种情况下,没有竞争条件(除了将事件插入队列)。如果您正在使用即用型队列而不是自己编码,那么它应该足够有效。

另请参阅Actors模型。

答案 1 :(得分:3)

Atomics确实比传统锁更有效,因为它们具有非阻塞行为,即等待访问内存位置的线程不会进行上下文切换,这样可以节省大量时间。

可能需要同步的最佳准则是了解如何尽可能减少关键部分的大小。一般的想法包括:

  1. 当只有部分线程需要写入时,使用读写锁而不是完全锁。
  2. 找到重组代码的方法,以减少关键部分的大小。
  3. 更新单个变量时使用atomics。
  4. 请注意,传统上需要锁定的某些算法和数据结构具有无锁版本(但它们更复杂)。

答案 2 :(得分:2)

好吧,首先,Atomic类使用锁定(通过synchronized和volatile关键字)就像你自己手动完成一样。

其次,不变性对于多线程很有用,你不再需要监视锁等等,但那是因为你只能读取你的不可变量,你可以修改它们。

如果要避免多线程Java程序中的竞争条件(即多个线程念念和读取相同的数据),则无法摆脱synchronized / volatile。你最好的选择是,如果你想要更好的性能,至少要避免一些内置的线程安全类,它们会进行更通用的锁定,并使你自己的实现更加依赖于你的上下文,从而可能允许你使用更多粒子同步&锁定收购。

查看Ehcache家伙完成的BlockingCache实现;

http://www.massapi.com/source/ehcache-2.4.3/src/net/sf/ehcache/constructs/blocking/BlockingCache.java.html

答案 3 :(得分:2)

其中一个选择是共享objects immutable。查看this post了解更多详情。

答案 4 :(得分:1)

每秒最多可以执行5000万次锁定/解锁。如果你想让它更有效率,我建议使用更多的课程粒度锁定。即不要锁定每一件小东西,但要锁定更大的物体。一旦你拥有比线程更多的锁,你就不太可能有争用,并且拥有更多的锁可能只会增加开销。