ReetrantLock锁

ReetrantLock锁的初步介绍

	public ReentrantLock() { //默认new一个ReentrantLock是创建一个非公平锁
        sync = new NonfairSync();
    }

lock方法

public void lock() {
        sync.lock();//默认是个非公平锁
    }

sync.lock方法是NonfairSync静态内部类的lock方法

static final class NonfairSync extends Sync { //Sync继承了AbstractQueuedSynchronizer(后面要说的AQS)
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
        	//AbstractQueuedSynchronizer.compareAndSetState方法,实际上是调用unsafe类的方法
        	//unsafe.compareAndSwapInt(this, stateOffset, expect, update);这里使用cas来修改stateOffset锁偏移量参数值
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
            	//获取锁
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

acquire–>AbstractQueuedSynchronizer.acquire

  public final void acquire(int arg) {
  /***
  **tryAcquire方式就是上面NonfairSync类具体的实现
  **addWaiter增加等待队列
  **
  **/
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

nonfairTryAcquire方法

	final boolean nonfairTryAcquire(int acquires) {//尝试获取锁
            final Thread current = Thread.currentThread();//获取当前线程
            int c = getState();//AbstractQueuedSynchronizer.state当前状态
            if (c == 0) {//如果状态为0,则处于一种无锁的状态
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);//然后将AbstractQueuedSynchronizer要执行的线程设置成当前线程
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {//如果要执行的线程==当前线程
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            //否则尝试获取锁失败
            return false;
        }

acquireQueued,获取线程队列

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {//如果是第一个线程,则会再次尝试去获取锁
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
        //如果队列获取失败,则取消获取,并释放锁
            if (failed)
                cancelAcquire(node);
        }
    }

shouldParkAfterFailedAcquire

private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
            如果这个节点已经准备去请求设置一个发布的状态信号,以致它可以安全的上锁
             */
            return true;
        if (ws > 0) {
            /*当ws>0,前一个线程被取消则跳过前置任务和指示重试。
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
             //当=0或者-3的时候,说明当前该线程是处于一种释放锁的状态,则上面的while结束循环
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);//这里又用到了CAS技术,这里后面在分析
        }
        return false;
    }

parkAndCheckInterrupt

private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);//这里类似线程wait
        return Thread.interrupted();
    }

​ 总结:ReentrantLock使用的是cas技术+等待队列来实现+LockSupport该类是实现,所谓的AQS就是指AbstractQueuedSynchronizer(抽象同步队列)。说白了ReentrantLock就是AQS的一种实现。尝试的去获取锁,也就是线程状态(根据线程的定义状态的去是比较替换来实现,cas(compareAndSwap)是重点)

CAS

CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术。简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替换当前变量的值。

cas技术主要实现基础类UnSafe,也有很多基于Unsafe的实现类在java.concurrent.atomic包下的一些类的compareAndSet的是实现;例如AtomicInteger

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

UnSafe调用的native的修饰的方法也就是虚拟机C++的实现

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

基于openjdk1.8是分析compareAndSwapInt的本地方法实现,找到对应的unsafe.cpp(这里为什么我可以断定的是unsafe.cpp文件呢?不妨可以先初步了解一下jni,看个小demo就可以了https://www.cnblogs.com/dengpeng1004/p/8745186.html)

unsafe.cpp中compareAndSwapInt的实现

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");//这句代码实际上的实现没有多大意义,可以忽略
  oop p = JNIHandles::resolve(obj);//这里将obj句柄解析到oop中。JNIHandles::resolve在jniHandles.hpp找到
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;//这句代码才是关键
UNSAFE_END

jniHandles::resolve

// Resolve handle into oop
  inline static oop resolve(jobject handle);

index_oop_from_field_offset_long是在jvm.cpp中,这里是做了内存地址偏移(这里不知道怎么去表达,麻烦各路大佬可以帮忙解答一下)

static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
  assert_field_offset_sane(p, field_offset);
  jlong byte_offset = field_offset_to_byte_offset(field_offset);

  if (sizeof(char*) == sizeof(jint)) {   // (this constant folds!)
    return (address)p + (jint) byte_offset;
  } else {
    return (address)p +        byte_offset;
  }
}

Atomic::cmpxchg(x, addr, e),在atomic.cpp中,最终会根据具体的宿主环境内联具体的实现,具体我们参照include的atomic.inline.hpp头文件

// Performs atomic compare of *dest and compare_value, and exchanges *dest with exchange_value
  // if the comparison succeeded.  Returns prior value of *dest.  Guarantees a two-way memory
  // barrier across the cmpxchg.  I.e., it's really a 'fence_cmpxchg_acquire'.
inline static jint     cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value);

atomic.inline.hpp

//这里我的理解是,会调用对应的平台方法的实现
#ifndef SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP
#define SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP

#include "runtime/atomic.hpp"

// Linux
#ifdef TARGET_OS_ARCH_linux_x86
# include "atomic_linux_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_sparc
# include "atomic_linux_sparc.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_zero
# include "atomic_linux_zero.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_arm
# include "atomic_linux_arm.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_linux_ppc
# include "atomic_linux_ppc.inline.hpp"
#endif

// Solaris
#ifdef TARGET_OS_ARCH_solaris_x86
# include "atomic_solaris_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_solaris_sparc
# include "atomic_solaris_sparc.inline.hpp"
#endif

// Windows
#ifdef TARGET_OS_ARCH_windows_x86
# include "atomic_windows_x86.inline.hpp"
#endif

// AIX
#ifdef TARGET_OS_ARCH_aix_ppc
# include "atomic_aix_ppc.inline.hpp"
#endif

// BSD
#ifdef TARGET_OS_ARCH_bsd_x86
# include "atomic_bsd_x86.inline.hpp"
#endif
#ifdef TARGET_OS_ARCH_bsd_zero
# include "atomic_bsd_zero.inline.hpp"
#endif

#endif // SHARE_VM_RUNTIME_ATOMIC_INLINE_HPP

atomic_linux_x86.inline.hpp简单的已这个linux_x86这个系统平台的实现来讲:

inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
 //主要是执行cmpxchgq汇编指令来操作内存
  bool mp = os::is_MP();
  __asm__ __volatile__ (LOCK_IF_MP(%4) "cmpxchgq %1,(%3)"
                        : "=a" (exchange_value)
                        : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
                        : "cc", "memory");
  return exchange_value;
}

LOCK_IF_MP

#define LOCK_IF_MP(mp) "cmp $0, " #mp "; je 1f; lock; 1: "//这里会有加锁的操作

is_MP

 static inline bool is_MP() {//返回处理器的个数
    // During bootstrap if _processor_count is not yet initialized
    // we claim to be MP as that is safest. If any platform has a
    // stub generator that might be triggered in this phase and for
    // which being declared MP when in fact not, is a problem - then
    // the bootstrap routine for the stub generator needs to check
    // the processor count directly and leave the bootstrap routine
    // in place until called after initialization has ocurred.
    return (_processor_count != 1) || AssumeMP;
  }

链接: https://pan.baidu.com/s/166T7qA6YDmUo4uuzFmOcjQ 提取码: 57dj;有openjdk1.8的源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值