2012-04-26 33 views

回答

4

只有方法本地的变量/引用。或者确保任何实例变量都是不可变的。

+0

不可变的实例变量是否可以接受? – duffymo 2012-04-26 09:48:25

+0

@duffymo编辑 – NimChimpsky 2012-04-26 09:50:16

+0

不错 - 短而重要。 – 2016-11-18 12:16:16

4

如果没有可变性,一切都是线程安全的,那么可以通过使所有数据不可变,使您的代码成为线程安全的。其次,你可能想看看Java并发API,它提供了读/写锁定的功能,以便在有很多读者和一些作者的情况下执行更好。纯同步关键字也会阻止两位读者。

7

实际上,很多方面:

  1. 无需同步在所有如果你没有可变状态。
  2. 如果可变状态局限于单个线程,则不需要同步。这可以通过使用局部变量或java.lang.ThreadLocal来完成。
  3. 您也可以使用内置同步器。 java.util.concurrent.locks.ReentrantLock与使用​​块和方法访问的锁具有相同的功能,并且功能更强大。
+1

我更喜欢(2),但我不确定它是否可能在不使用'synchronized'关键字的情况下实现消息传递。我可以制作一个没有“同步”的生产者 - 消费者队列吗? – 2012-04-26 10:07:17

+1

没关系 - 我可以通过使用java.util.concurrent.Semaphore。 – 2012-04-26 10:10:06

+1

@MartinJames任何类似队列和交换器的并发类都可以在没有同步的情况下使用。 (他们使用Lock来代替)Disrupter支持不锁定或同步的消息传递。 (我有一个库,它也这样做) – 2012-04-26 11:27:08

-2

为什么你需要这样做?

仅使用本地变量/引用不会解决大多数复杂的业务需求。 另外,如果实例变量是不可变的,它们的引用仍然可以被其他线程改变。

其中一种选择是使用类似于SingleThreadModel的东西,但非常不鼓励和弃用。

ü也可以看看并发API通过卡尔

+0

“如果实例变量是不可变的,它们的引用仍然可以改变”不,它们不能 – NimChimpsky 2012-04-26 10:03:37

+0

可以解释。我怎么看它是如果我有一个instanace变量String s =“xyz”,我的thread1可以改变它的引用s =“abc”;和thread2现在会得到s =“abc” – Kshitij 2012-04-26 10:08:15

+0

s是一个引用,它已经改变,它不是不可变的,你需要“最终字符串s” – NimChimpsky 2012-04-26 10:11:51

1

上面建议保持预见性您必须确保所有访问的可变数据由顺序或处理由并行访问的问题。

最严重的保护使用​​关键字。除此之外,至少有两层可能性,每一层都有其优点。

锁/信号灯

这些可以是非常有效的。例如,如果您的结构是由多个线程读取的,但只能更新一个,则可能会发现ReadWriteLock有用。

如果您选择锁定来匹配算法,锁定可以更加高效。

原子能

例如使用AtomicReference可以经常提供完全无锁的功能。这通常可以提供巨大的好处。

原子背后的推理是让他们失败,但告诉你他们失败的方式,你可以处理它。

例如,如果要更改某个值,则可以读取该值,然后只要它仍旧是旧值就可以写入新值。这被称为“比较和设置”或cas,通常可以在硬件中实现,因此非常有效。所有你需要的是这样的:

long old = atomic.get(); 
while (!atomic.cas(old, old+1)) { 
    // The value changed between my get and the cas. Get it again. 
    old = atomic.get(); 
} 

但是,请注意,可预测性并不总是要求。