1、 原子引用
为什么需要原子引用?因为引用类型也需要被保护
- AtomicReference
- AtomicMarkableReference
- AtomicStampedReference
package com.sharing_model.no_lock;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 原子引用
*/
public class AtomicReferenceTest {
public static void main(String[] args) {
DecimalAccount.demo(new DecimalAccountCas(new BigDecimal("10000")));
}
}
class DecimalAccountCas implements DecimalAccount {
private AtomicReference<BigDecimal> balance;
public DecimalAccountCas(BigDecimal balance) {
this.balance = new AtomicReference<>(balance);
}
@Override
public BigDecimal getBalance() {
return balance.get();
}
@Override
public void withdraw(BigDecimal amount) {
while (true) {
BigDecimal prev = balance.get();
BigDecimal next = prev.subtract(amount);
if (balance.compareAndSet(prev, next)) {
break;
}
}
}
}
interface DecimalAccount {
//获取余额
BigDecimal getBalance();
//取款
void withdraw(BigDecimal amount);
static void demo(DecimalAccountCas account) {
List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
ts.add(new Thread(() -> {
account.withdraw(new BigDecimal(10));
}));
}
long start = System.nanoTime();
ts.forEach(Thread::start);
ts.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
long end = System.nanoTime();
System.out.println("剩余钱数: " + account.getBalance());
}
}
2、 ABA问题
package com.sharing_model.no_lock;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* 原子引用
*/
public class AtomicReferenceTest {
public static void main(String[] args) {
DecimalAccount.demo(new DecimalAccountCas(new BigDecimal("10000")));
}
}
class DecimalAccountCas implements DecimalAccount {
private AtomicReference<BigDecimal> balance;
public DecimalAccountCas(BigDecimal balance) {
this.balance = new AtomicReference<>(balance);
}
@Override
public BigDecimal getBalance() {
return balance.get();
}
@Override
public void withdraw(BigDecimal amount) {
while (true) {
BigDecimal prev = balance.get();
BigDecimal next = prev.subtract(amount);
if (balance.compareAndSet(prev, next)) {
break;
}
}
}
}
interface DecimalAccount {
//获取余额
BigDecimal getBalance();
//取款
void withdraw(BigDecimal amount);
static void demo(DecimalAccountCas account) {
List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
ts.add(new Thread(() -> {
account.withdraw(new BigDecimal(10));
}));
}
long start = System.nanoTime();
ts.forEach(Thread::start);
ts.forEach(t -> {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
long end = System.nanoTime();
System.out.println("剩余钱数: " + account.getBalance());
}
}
3、 AtomicStampedReference
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wg16MBkV-1607688054940)(C:/Users/lenovo/AppData/Roaming/Typora/typora-user-images/image-20201206125653337.png)]](/https://i-blog.csdnimg.cn/blog_migrate/fbf5cdf082f4313d1a0e32ccf74c8673.png)
package com.sharing_model.no_lock;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;
/**
* 通过添加Stamp(版本号),来判断是否被人修改过,从而解决ABA问题
*/
public class AtomicStampedReferenceTest {
static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
public static void main(String[] args) throws InterruptedException {
//获取这个变量A的值和版本号
String prev = ref.getReference(); //A
int stamp = ref.getStamp(); //0
System.out.println("初始版本号: " +stamp );
other();
Thread.sleep(1000);
System.out.println("所有修改完成之后的版本号: " + ref.getStamp()); //2
//尝试修改为C
System.out.println("change A -> C : " + ref.compareAndSet(prev, "C", stamp, stamp + 1));
}
private static void other() throws InterruptedException {
new Thread(() -> {
int stamp = ref.getStamp();
System.out.println("A -> B之前的版本号: " + stamp);
System.out.println("change A -> B: " + ref.compareAndSet(ref.getReference(), "B", stamp, stamp + 1));
},"t1").start();
Thread.sleep(500);
new Thread(() -> {
int stamp = ref.getStamp();
System.out.println("B -> A之前的版本号: " + stamp);
System.out.println("change B -> A: " + ref.compareAndSet(ref.getReference(), "A", stamp, stamp +1));
},"t2").start();
}
}
4、 AtomicMarkableReference
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5expdtBT-1607688054951)(C:/Users/lenovo/AppData/Roaming/Typora/typora-user-images/image-20201206133242837.png)]](/https://i-blog.csdnimg.cn/blog_migrate/9c3848310fa5bd311c7d7dde0d5e1d6a.png)
package com.sharing_model.no_lock;
import java.util.concurrent.atomic.AtomicMarkableReference;
/**
*AtomicMarkableReference:
* 和 AtomicStampedReference 不同之处在于,不关心引用变量更改了几次,只是单纯的关心是否更改过,所以就有了AtomicMarkableReference
*/
public class AtomicMarkableReferenceTest {
public static void main(String[] args) throws InterruptedException {
GarbageBag bag = new GarbageBag("装满了垃圾");
//参数 mark 可以看成一个标记,表示垃圾袋满了
AtomicMarkableReference<GarbageBag> ref = new AtomicMarkableReference<>(bag, true);
System.out.println("start...");
GarbageBag prev = ref.getReference();
System.out.println(prev.toString());
Thread.sleep(1000);
System.out.println("想更换一只新垃圾袋?");
boolean success = ref.compareAndSet(prev, new GarbageBag("空垃圾袋"),true, false);
System.out.println("换了吗?" + success);
System.out.println(ref.getReference().toString());
}
}
class GarbageBag {
String value;
public GarbageBag(String value) {
this.value = value;
}
}

573

被折叠的 条评论
为什么被折叠?



