CAS

1. ABA问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
static AtomicInteger atomicInteger = new AtomicInteger(100);
static AtomicStampedReference<Integer> stampedReference = new AtomicStampedReference<>(100,1);

public static void main(String[] args)
{
new Thread(() -> {
int stamp = stampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t"+"首次版本号:"+stamp);

//暂停500毫秒,保证后面的t4线程初始化拿到的版本号和我一样
try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }

stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1);
System.out.println(Thread.currentThread().getName()+"\t"+"2次流水号:"+stampedReference.getStamp());

stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1);
System.out.println(Thread.currentThread().getName()+"\t"+"3次流水号:"+stampedReference.getStamp());

},"t3").start();

new Thread(() -> {
int stamp = stampedReference.getStamp();
System.out.println(Thread.currentThread().getName()+"\t"+"首次版本号:"+stamp);

//暂停1秒钟线程,等待上面的t3线程,发生了ABA问题
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

boolean b = stampedReference.compareAndSet(100, 2022, stamp, stamp + 1);

System.out.println(b+"\t"+stampedReference.getReference()+"\t"+stampedReference.getStamp());

},"t4").start();

}

private static void abaHappen()
{
new Thread(() -> {
atomicInteger.compareAndSet(100,101);
try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
atomicInteger.compareAndSet(101,100);
},"t1").start();

new Thread(() -> {
try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(atomicInteger.compareAndSet(100, 2022)+"\t"+atomicInteger.get());
},"t2").start();
}
}

运行结果

t1 首次版本号:1
t2 首次版本号:1
t1 2次流水号:2
t1 3次流水号:3
false 100 3

2. AtomicReference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Getter
@ToString
@AllArgsConstructor
class User
{
String userName;
int age;
}


public class AtomicReferenceDemo
{
public static void main(String[] args)
{
AtomicReference<User> atomicReference = new AtomicReference<>();

User z3 = new User("z3",22);
User li4 = new User("li4",28);

atomicReference.set(z3);

System.out.println(atomicReference.compareAndSet(z3, li4)+"\t"+atomicReference.get().toString());
System.out.println(atomicReference.compareAndSet(z3, li4)+"\t"+atomicReference.get().toString());


}
}
运行结果

true User(userName=li4, age=28)
false User(userName=li4, age=28)

3. AtomicStampedReference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@NoArgsConstructor
@AllArgsConstructor
@Data
class Book
{
private int id;
private String bookName;
}

public class AtomicStampedDemo
{
public static void main(String[] args)
{
Book javaBook = new Book(1,"javaBook");

AtomicStampedReference<Book> stampedReference = new AtomicStampedReference<>(javaBook,1);

System.out.println(stampedReference.getReference()+"\t"+stampedReference.getStamp());

Book mysqlBook = new Book(2,"mysqlBook");

boolean b;
b = stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);

System.out.println(b+"\t"+stampedReference.getReference()+"\t"+stampedReference.getStamp());


b = stampedReference.compareAndSet(mysqlBook, javaBook, stampedReference.getStamp(), stampedReference.getStamp() + 1);

System.out.println(b+"\t"+stampedReference.getReference()+"\t"+stampedReference.getStamp());

}
}
运行结果

Book(id=1, bookName=javaBook) 1
true Book(id=2, bookName=mysqlBook) 2
true Book(id=1, bookName=javaBook) 3

4. CAS

1
2
3
4
5
6
7
8
9
10
11
12
{
public static void main(String[] args)
{
AtomicInteger atomicInteger = new AtomicInteger(5);

System.out.println(atomicInteger.compareAndSet(5, 2022)+"\t"+atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(5, 2022)+"\t"+atomicInteger.get());

atomicInteger.getAndIncrement();
}
}

运行结果

true 2022
false 2022

5. CAS Lock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 题目:实现一个自旋锁,复习CAS思想
* 自旋锁好处:循环比较获取没有类似wait的阻塞。
*
* 通过CAS操作完成自旋锁,A线程先进来调用myLock方法自己持有锁5秒钟,B随后进来后发现
* 当前有线程持有锁,所以只能通过自旋等待,直到A释放锁后B随后抢到。
*/
public class SpinLockDemo
{
AtomicReference<Thread> atomicReference = new AtomicReference<>();

public void lock()
{
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName()+"\t"+"----come in");
while (!atomicReference.compareAndSet(null, thread)) {

}
}

public void unLock()
{
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
System.out.println(Thread.currentThread().getName()+"\t"+"----task over,unLock...");
}

public static void main(String[] args)
{
SpinLockDemo spinLockDemo = new SpinLockDemo();

new Thread(() -> {
spinLockDemo.lock();
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
spinLockDemo.unLock();
},"A").start();

//暂停500毫秒,线程A先于B启动
try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }

new Thread(() -> {
spinLockDemo.lock();

spinLockDemo.unLock();
},"B").start();


}
}

运行结果

A —-come in
B —-come in
A —-task over,unLock…
B —-task over,unLock…


本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.