Lock

Posted on Jun 12, 2023

Lock的实现都有种共通性:一个原子操作,再加上一个队列,当然也可以直接失败,但是大多数实现都是选择去队列里排队

比如synchronized,它就一个CAS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
template<>
template<typename T>
inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value,
                                                T volatile* dest,
                                                T compare_value,
                                                atomic_memory_order /* order */) const {
  STATIC_ASSERT(1 == sizeof(T));
  __asm__ volatile ("lock cmpxchgb %1,(%3)"
                    : "=a" (exchange_value)
                    : "q" (exchange_value), "a" (compare_value), "r" (dest)
                    : "cc", "memory");
  return exchange_value;
}

这个CAS操作是由CPU来保证原子性的

1
lock cmpxchgb

cmpxchgb:x86提供的CAS指令 lock:单核CPUcmpxchgb本身已经是原子的,加个lock保证多核场景下的原子性

同时它用队列来维护没有获取到LockThreadobjectMonitor.cpp里也有清楚的注释

1
2
3
4
5
// The Spin failed -- Enqueue and park the thread ...
ObjectWaiter node(Self);
node._next = nxt = _cxq;

Self->_ParkEvent->park();

park是一个syscall,告诉kernel放弃时间片,等待调度

JDK里的ReentrantLock实现也和synchronized非常相似,也是CASQueue

1
2
3
public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }