来自Java AtomicReferenceFieldUpdater
文档:
请注意,
compareAndSet
此类中方法的保证比其他原子类弱.因为此类不能确保该领域的所有应用都适合于原子访问目的,它可以保证原子性和可变语义只相对于其他调用compareAndSet
和set
.
这意味着我无法进行正常的易失性写入compareAndSet
,但必须使用set
.它没有提到任何关于get
.
这是否意味着我仍然可以读取具有相同原子性保证的volatile字段 - 所有写入之前的所有写入set
或者compareAndSet
对读取volatile字段的所有人都可见?
还是我使用get
上AtomicReferenceFieldUpdater
,而不是在球场上挥发读?
如果您有参考,请发布参考.
谢谢.
编辑:
从Java Concurrency in Practice中,他们唯一说的是:
updater类的原子性保证比常规原子类弱,因为您无法保证不会直接修改基础字段 - compareAndSet和算法方法仅保证原子性与使用原子字段更新器方法的其他线程相关.
同样,没有提到其他线程应该如何读取这些volatile字段.
另外,我是否正确地假设"直接修改"是一个常规的易失写?
我们的许多代码都是遗留的,但我们正在转向"大数据"后端,我正在尝试传播新的API调用,鼓励使用最新的Spring库等.我们的一个问题是应用层ID代.由于我不理解的原因,更高的权限需要顺序BigInteger.我会让它们随机重新生成并重新尝试失败的插入但我完成了否决.
磕磕绊绊地说,我处于一个需要增加并在线程中获得BigInteger并以安全和高效的方式执行的位置.我之前从未使用过AtomicReference,但它看起来非常接近完美的应用程序.现在我们有一个同步代码块,这会严重损害我们的性能.
这是正确的方法吗?语法示例?
我应该提一下这个模块的工作方式,它使用存储过程命中数据库以获取要使用的一系列值.一次只有几万个,所以它只发生在20分钟一次.这使得各种服务器不会相互踩踏,但它也增加了必须将BigInteger设置为任意后续值的皱纹.当然,这也需要线程安全.
PS我仍然认为我的随机生成想法比处理所有这些线程的东西更好.一个BigInteger是一个非常大的数字,两次产生相同的几率的几率必须接近零.
源代码是一回事.
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
Run Code Online (Sandbox Code Playgroud)
重点是什么?
假设我有一个AtomicReference
对象列表:
AtomicReference<List<?>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>());
Run Code Online (Sandbox Code Playgroud)
线程A将元素添加到此列表:batch.get().add(o);
稍后,线程B获取列表,例如,将其存储在DB中:insertBatch(batch.get());
在写入(线程A)和读取(线程B)时,是否必须执行其他同步以确保线程B按照A离开的方式查看列表,或者由AtomicReference处理?
换句话说:如果我有一个可变对象的AtomicReference,并且一个线程更改了该对象,其他线程是否会立即看到此更改?
编辑:
也许一些示例代码是有序的:
public void process(Reader in) throws IOException {
List<Future<AtomicReference<List<Object>>>> tasks = new ArrayList<Future<AtomicReference<List<Object>>>>();
ExecutorService exec = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; ++i) {
tasks.add(exec.submit(new Callable<AtomicReference<List<Object>>>() {
@Override public AtomicReference<List<Object>> call() throws IOException {
final AtomicReference<List<Object>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>(batchSize));
Processor.this.parser.parse(in, new Parser.Handler() {
@Override public void onNewObject(Object event) {
batch.get().add(event);
if (batch.get().size() >= batchSize) {
dao.insertBatch(batch.getAndSet(new …
Run Code Online (Sandbox Code Playgroud) 我不明白这两者之间的区别:
AtomicReference<Integer> atomicReference = new AtomicReference<>(1);
Run Code Online (Sandbox Code Playgroud)
与
AtomicInteger atomicInteger = new AtomicInteger(1);
Run Code Online (Sandbox Code Playgroud)
有人一般可以说何时使用AtomicReference?希望可以有人帮帮我.谢谢.
有没有办法实现一种类型的引用,其值可以与另一个原子交换?
在Java中,我们AtomicReference
可以使用本地变量而不是其他变量进行交换AtomicReference
.
你可以做:
AtomicReference r1 = new AtomicReference("hello");
AtomicReference r2 = new AtomicReference("world");
Run Code Online (Sandbox Code Playgroud)
并将它们与两个操作组合交换:
r1.set(r2.getAndSet(r1.get()));
Run Code Online (Sandbox Code Playgroud)
但是这使得它们之间处于不一致状态,两者都包含在内"hello"
.即使你可以原子地交换它们,你仍然无法原子地读取它们(作为一对).
我希望能做的是:
PairableAtomicReference r1 = new PairableAtomicReference("hello");
PairableAtomicReference r2 = new PairableAtomicReference("world");
AtomicRefPair rp = new AtomicRefPair(r1, r2);
Run Code Online (Sandbox Code Playgroud)
然后
Object[] oldVal, newVal;
do {
oldVal = rp.get();
newVal = new Object[] {oldVal[1], oldVal[0]};
} while (! rp.compareAndSet(oldVal, newVal));
Run Code Online (Sandbox Code Playgroud)
交换值,并在另一个线程中:
AtomicRefPair otherRP = new AtomicRefPair(r1, r2);
System.out.println(Arrays.toString(otherRP.get()));
Run Code Online (Sandbox Code Playgroud)
并确保输出将是[hello, world]
或[world, hello]
.
笔记:
r1
并且r2
为此操作配对,但是另一个线程可能会独立配对,说r1 …
在Java中,存在AtomicReference类.这是否意味着设置引用本身并不是原子操作?
例如,这是不是线程安全的(假设返回的值不能修改)?:
public void someMethod()
{
this.someList = Collections.unmodifiableList(new LinkedList<Object>());
}
public List<Object> getReadOnlyList()
{
return someList;
}
Run Code Online (Sandbox Code Playgroud)
在C#怎么样?
我在多线程程序中使用一些全局结构,其中一些成员被多个线程同时修改,另一些则不然。
我没有将任何成员定义为 易失性的,但每当我使用此成员进行读取和写入时,我都会使用原子内置函数,例如 __sync_fetch_and_add。
问题是,我应该定义这个成员还是整个结构体?
我认为由于这个内置函数(锁定前缀),编译器必须访问内存而不是任何寄存器,我是否应该担心其他不会导致竞争条件的成员。
我检查了编译器(gcc 4.6.2)的汇编输出,看来我的假设是正确的。
这是测试代码。
int sum = 0;
for (i=0; i<2000000000; i++) {
sum += i;
}
Run Code Online (Sandbox Code Playgroud)
汇编输出(-O2 -S -masm=intel)
L2:
add edx, eax
inc eax
cmp eax, 2000000000
jne L2
Run Code Online (Sandbox Code Playgroud)
所以编译器永远不会访问内存(eax = i, edx = sum)
这是第二个测试代码。
volatile int sum = 0;
for (i=0; i<2000000000; i++) {
sum += i;
}
Run Code Online (Sandbox Code Playgroud)
装配输出
L2:
mov edx, DWORD PTR [esp+28]
add edx, eax
mov DWORD PTR [esp+28], edx
inc eax
cmp eax, 2000000000
jne L2
Run Code Online (Sandbox Code Playgroud)
编译器每次都按预期访问内存求和。 …
我必须将线程之间的访问同步到共享对象,该对象的状态由几个字段组成。说:
class Shared{
String a; Integer b;
//constructor, getters and setters
....
}
Run Code Online (Sandbox Code Playgroud)
我可能有很多线程正在读取此对象,
//readers
shared.getA();
shared.getB();
Run Code Online (Sandbox Code Playgroud)
并且只有一个线程将在特定点写入:
//writer
shared.setA("state");
shared.setB(1);
Run Code Online (Sandbox Code Playgroud)
现在我的问题是如何确保读取线程不会在不一致状态下找到共享库。
我读过许多答案,它们表示为了volatile
确保线程之间的一致性是解决方案,但我不确定它如何在多个字段上工作。例如,够了吗?
volatile String a; volatile Integer b;
Run Code Online (Sandbox Code Playgroud)
另一个解决方案是使共享对象不可变,并使用AtomicReference,
AtomicReference<Shared> shared = ....
Run Code Online (Sandbox Code Playgroud)
然后作者将交换引用:
Shared prev = shared.get();
Shared newValue = new Shared("state",1);
while (!shared.compareAndSet(prev, newValue))
Run Code Online (Sandbox Code Playgroud)
那是正确的方法吗?谢谢!
更新在我的设置中,共享对象是从检索的ConcurrentHashMap<Id,Shared>
,因此注释同意使用的方法是使用不变方法或通过同步所有共享上的更新。但是,出于完整性考虑,很高兴知道上面的解决方案ConcurrentHashMap<Id,AtomicReference<Shared>>
是可行的还是错误的,或者仅仅是多余的。有人可以解释吗?谢谢!
我经常发现自己使用这个习语:
AtomicReference<MyCoolObject> coolReference = new AtomicReference(new MyCoolObject());
getOptionalValue().ifPresent(presentValue -> {
coolReference.set(new MyCoolObject(presentValue));
});
return coolReference.get();
Run Code Online (Sandbox Code Playgroud)
这是一个坏习惯,还是一个合法的使用AtomicReference
?
atomicreference ×10
java ×9
concurrency ×4
volatile ×2
atomic-swap ×1
atomicity ×1
biginteger ×1
c# ×1
gcc ×1
increment ×1
interlocked ×1
jsr166 ×1
lambda ×1
mutable ×1