Sha*_*kar -1 java multithreading atomicreference
AtomicReference 实例使用 Unsafe CAS 操作来利用处理器指令进行锁定。但是我有点困惑它在复杂对象的情况下是如何工作的。
例如,让我们假设我有一个 Person 类的实例(id、firstName、lastName)。我将对象实例共享给多个线程 t1、t2 和 t3。由于操作应该是原子的,所以我不会共享 Person 类对象实例,而是将该对象包装到 AtomicReference 实例中并与所有线程共享。
现在线程 t1 只更新 firstName,线程 t2 只更新 lastName,线程 t3 更新 firstName 和 lastName。之后每个线程都会调用 compareAndSet 方法来反映新的变化。
此外,我正在使用易失性引用,以便写入可以发生在主内存中并对所有线程可见。
我想明白:
在上面的场景中,当 compareAndSet 被调用时,Person 类实例(例如 id、firstName、lastName)的预期值和新值之间将比较哪些内容?
假设线程 t1 更新了 firstName 并调用了 compareAndSet。线程 t2 已更新 lastName 并且将调用 compareAndSet。在这种情况下,AtomicReference 如何保证线程 t2 不会擦除线程 t1 所做的更改,即更新 firstName?
假设 2 个线程 t1 和 t2 同时调用 compareAndSet 那么谁将赢得比赛,而其他失败的线程会怎样?
如果您共享了可变Person对象,则AtomicReference根本不会帮助您。每次要应用更改时,您都需要使Person不可变的并创建一个新的Person。这样,您的线程更新多少个字段都无关紧要。所以假设你有这样一个不可变的Person类:
public class Person {
public final int id;
public final String firstName, lastName;
public Person(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
}
Run Code Online (Sandbox Code Playgroud)
那么您的线程可能会执行以下操作
AtomicReference<Person> ref; // shared reference
public void updateFirstName(String firstName) {
Person curPerson, newPerson;
do {
curPerson = ref.get();
newPerson = new Person(curPerson.id, firstName, curPerson.lastName);
} while (!ref.compareAndSet(curPerson, newPerson));
}
public void updateLastName(String lastName) {
Person curPerson, newPerson;
do {
curPerson = ref.get();
newPerson = new Person(curPerson.id, curPerson.firstName, lastName);
} while (!ref.compareAndSet(curPerson, newPerson));
}
public void updateName(String firstName, String lastName) {
Person curPerson, newPerson;
do {
curPerson = ref.get();
newPerson = new Person(curPerson.id, firstName, lastName);
} while (!ref.compareAndSet(curPerson, newPerson));
}
Run Code Online (Sandbox Code Playgroud)
调用这样的方法,您将Person整体更新并且不会有任何竞争条件。
至于你的第三个问题,没有指定谁会赢,但是失败的线程只会再迭代一次并相应地更新另一个字段,所以你最终会更新这两个字段。