gpt4 book ai didi

java - 如果我使用synchronized,我应该使用 volatile 吗?

转载 作者:行者123 更新时间:2023-12-01 06:18:43 24 4
gpt4 key购买 nike

如果我使用synchronized处理某些可变状态,我每次都应该使用 volatile 吗?

  1. 同步使我(状态/线程)安全
  2. volatile 使线程更新关于共享可变状态

如果我关心要更新的线程,那么我应该在任何地方都放置 volatile

编辑:有两个用例:

1.

1000 个线程读取和写入此对象(它们希望更新状态 a):

 class A {
private int a;
public synchronized int getA() {...}
public void setA(int a) {...}
}

2.

ThreadA 有 1000 个线程。他们希望更新状态 a

class ThreadA extends Thread {
private int a;
public void run() { synchronized(a) { ... } }
}

最佳答案

与许多性能问题一样,真正的问题是简单性和清晰度。我建议使用同步或 volatile ,因为使用两者可能会造成混淆。两者同时使用是多余的,因此效率稍低,但不太可能足够重要。我会更担心如何使代码尽可能易于理解,并且不会做超出您需要的事情。

在第一种情况下,只有 volatile 才有意义(或一致使用同步)

class A {
private volatile int a;
public int getA() {...}
public void setA(int a) {...}
}

在第二种情况下,同步本地对象是没有意义的,您可以将其删除。我也不会扩展 Thread,这是不好的做法。

虽然您可能有 1000 个线程,但您可能只拥有 8-16 个 CPU,但拥有如此多的 CPU 绑定(bind)线程并不是一个好主意。减少线程数量,您可能会通过减少开销来提高性能。

您应该将它们设计得尽可能独立,因为如果不能,单个线程可能会更快,因为它不会产生缓存一致性开销。

<小时/>

恕我直言,使用枚举比使用 Guava MemorizeSupplier 更简单,但速度更快

public class GuavaMain {
interface AAA {
int hashCode();
}

enum Singleton implements AAA {
INSTANCE
}

public static void main(String... ignored) {
Supplier<AAA> memoize = Suppliers.memoize(new Supplier<AAA>() {
@Override
public AAA get() {
return new AAA() {
};
}
});

for (int j = 0; j < 10; j++) {
int runs = 5000;
long time1 = System.nanoTime();
for (int i = 0; i < runs; i++) {
// call a method on out lazy instance
Singleton.INSTANCE.hashCode();
}
long time2 = System.nanoTime();
for (int i = 0; i < runs; i++) {
// call a method on out lazy instance
memoize.get().hashCode();
}
long time3 = System.nanoTime();
System.out.printf("enum took %,d ns and memorize took %,d ns avg%n",
(time2 - time1) / runs, (time3 - time2) / runs);
}
}
}

打印

enum took 179 ns and memorize took 301 ns avg
enum took 74 ns and memorize took 97 ns avg
enum took 62 ns and memorize took 175 ns avg
enum took 58 ns and memorize took 146 ns avg
enum took 58 ns and memorize took 147 ns avg
enum took 56 ns and memorize took 111 ns avg
enum took 36 ns and memorize took 86 ns avg
enum took 36 ns and memorize took 84 ns avg
enum took 36 ns and memorize took 82 ns avg
enum took 36 ns and memorize took 82 ns avg

关于java - 如果我使用synchronized,我应该使用 volatile 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16719004/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com