1

I know that ReentrantLock use AbstractQueuedSynchronizer(AQS) to implement Lock. But the detail of the realization, I can not understand.

I know that AQS use volatile, CAS and spin for synchronizing. But, these actions only control the "state" member.

Although, LockSupport.park and LockSupport.unpark can synchronize the cacheline of the thread. But if there is never contention, LockSupport methods will never be called. Like this: 1.Thread A start and run

2.Thread B start and run

3.Thread A:

lock.lock();
try{
  //modify some shared members
  ....
}finally{
  lock.unlock();
}

4.Then Thread B:

lock.lock();
try{
  //read shared members
  ....
}finally{
  lock.unlock();
}

No contention, thread B does not call LockSupport methods.

lock.lock() only CAS "state" member, and lock.unlock() modify the volatile "state" to 0.

Why thread B can seen the modification of thread A about shared members?

Why ReentrantLock can use as "synchronized"?

I did not see any code like fullFence to synchronize memory.

Which code realize the synchronizing of the cacheline of the thread ?

I saw the source code in android art vm and HotSpot vm.

In Android:

It uses std::atomic ->compare_exchange_strong and Heap::WriteBarrierField. These functions like only modify a field, not all the cachelines of a thread.

In HotSpot:

It uses Atomic::cmpxchg_ptr(It's asm code modify a field) and update_barrier_set. These functions also like only modify a field, not update all the cachelines of a thread.

Do I misunderstand?

1 Answer 1

1

The essence of the algorithm used by ReentrantLock is to use a compare and set operation to ensure that an earlier accessor of the lock has released it. The sequence of operations of interest is:

  • thread A acquired the lock, storing a value that identifies it in the state
  • thread A modifies the shared data
  • thread A releases the lock, storing an unlocked state identifier
  • thread B acquires the lock, receiving the unlocked state identifier.
  • thread B accesses the shared data

Each operation within a single thread has a happens-before relationship, guaranteeing memory availability within the thread. A compare and swap operation also provides a happens-before relationship between the call that set the value and the call that received it. Therefore, each operation on this list has a happens-before guarantee to the next. This is transitive, so we can see that "thread A modifies the shared data" happens before "thread B accesses the shared data", thus the lock works as expected.

3
  • I saw the source code in android art vm and HotSpot vm. In Android: It uses std::atomic ->compare_exchange_strong and Heap::WriteBarrierField. These functions like only modify a field, not all the cachelines of a thread. In HotSpot: It uses Atomic::cmpxchg_ptr(It's asm code modify a field) and update_barrier_set. These functions also like only modify a field, not update all the cachelines of a thread. Do I misunderstand?
    – ApeStack
    Mar 23, 2017 at 14:30
  • Compare and swap is defined to provide a happens-before relationship between the two relevant threads. How this happens is dependent on the particular implementation, but probably involves the processor providing an implicit memory barrier in the instruction used to implement the operation.
    – Jules
    Mar 23, 2017 at 14:38
  • Note that, for example, on x86, memory ordering respects transitive visibility, so an explicit memory barrier is not required there.
    – Jules
    Mar 23, 2017 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.