【Java】01-Java锁

img-cover

序号 锁类型 应用
1 乐观锁 CAS
2 悲观锁 synchronized, vector, hashtable
3 自旋锁 CAS
4 可重入锁 synchronized, Reentrantlock, Lock
5 读写锁 ReentrantReadWriteLock, CopyOnWriteArrayList, CopyOnWriteArraySet
6 公平锁 Reentrantlock(true)
7 非公平锁 synchronized, reentrantlock(false)
8 共享锁 ReentrantReadWriteLock中的读锁
9 独占锁 synchronized, vector, hashtable, ReentrantReadWriteLock中的写锁
10 重量级锁 synchronized
11 轻量级锁 锁优化技术
12 偏向锁 锁优化技术
13 分段所 ConcurrentHashMap
14 互斥锁 synchronized
15 同步锁 synchronized
16 死锁 互相请求对方的资源
17 锁粗化 锁优化技术
18 锁消除 锁优化技术

乐观锁

CAS(compare and swap / compare and set)

CAS:无锁,自旋锁,乐观锁,轻量级锁。

线程不会出现阻塞,不会切换线程调度,切换上下文,恢复上下文。

  1. Cas.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class CAS {

    private AtomicInteger num = new AtomicInteger(0);

    public Integer get() {
    return num.get();
    }

    public void add() {
    while (true) {
    int oldValue = num.get();
    int newValue = oldValue + 1;
    if (num.compareAndSet(oldValue, newValue)) {
    break;
    }
    }
    }

    }
  2. Main.java

    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
    public class Main {

    public static void main(String[] args) throws InterruptedException {
    CAS number = new CAS();

    long start = System.currentTimeMillis();

    Thread t1 = new Thread(() -> {
    for (int i = 0; i < 10000000; i++) {
    number.add();
    }
    });
    t1.start();

    Thread t2 = new Thread(() -> {
    for (int i = 0; i < 10000000; i++) {
    number.add();
    }
    });
    t2.start();
    t1.join();
    t2.join();

    long end = System.currentTimeMillis();
    System.out.println(end - start);

    System.out.println(number.get());
    }

    }

问题

原子性

  1. 底层调用

    1
    public final native boolean compareAndSetInt(Object var1, long var2, int var4, int var5);
  2. 底层调用的C代码

    1
    2
    3
    4
    5
    6
    UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
    UnsafeWraper("Unsafe_CompareAndSwapInt");
    oop p = JNIHandles::resolve(obj);
    jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
    return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
    UNSAFE_END
  3. Atomic::cmpxchg(x, addr, e)方法中重要的两条汇编指令

    1. lock
    2. cmpxchgq: compare and exchange

ABA问题

引入版本号,每次修改值之后,改变版本号。

  1. CAS.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class CAS {

    private final AtomicStampedReference<Integer> num = new AtomicStampedReference<>(0, 0);

    public Integer get() {
    return num.getReference();
    }

    public void add() {
    while (true) {
    int stamp = num.getStamp();
    Integer reference = num.getReference();
    boolean flag = num.compareAndSet(reference, reference + 1, stamp, stamp + 1);
    if (flag) {
    break;
    }
    }
    }

    }
  2. AtomicStampedReference: 带有版本号的CAS类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // initialRef: 初始值
    // initialStamp: 初始版本号
    public AtomicStampedReference(V initialRef, int initialStamp) {
    this.pair = AtomicStampedReference.Pair.of(initialRef, initialStamp);
    }

    // reference: 变量值
    // stamp: 版本号
    private static class Pair<T> {
    final T reference;
    final int stamp;

    private Pair(T reference, int stamp) {
    this.reference = reference;
    this.stamp = stamp;
    }

    static <T> AtomicStampedReference.Pair<T> of(T reference, int stamp) {
    return new AtomicStampedReference.Pair(reference, stamp);
    }
    }

悲观锁

自旋锁

可重入锁

读写锁

-------------本文结束感谢您的阅读-------------