zoukankan      html  css  js  c++  java
  • 3.1.1 重入锁 以及源码分析

    package 第三章.重入锁;

    import java.util.concurrent.locks.ReentrantLock;

    /**
    * Created by zzq on 2018/1/22.
    */
    public class ReentrantLockTest implements Runnable{
    public static ReentrantLock lock=new ReentrantLock(true);
    public static int a=0;
    public void run() {
    for (int i = 0; i < 1000000; i++) {
    lock.lock();
    try{
    a++;
    }finally {
    lock.unlock();
    }
    }
    }

    public static void main(String[] args) throws InterruptedException {
    ReentrantLockTest reentrantLockTest=new ReentrantLockTest();
    Thread thread1=new Thread(reentrantLockTest);
    Thread thread2=new Thread(reentrantLockTest);
    thread1.start();
    thread2.start();
    thread1.join();
    thread2.join();
    System.out.println(a);
    }
    }


    一。构造函数:

    ReentrantLock有两种类型的锁,公平锁和非公平锁,默认的是非公平锁。(如果设置为公平锁,那么就会根据执行的顺序,阻塞)

    1.默认情况 public ReentrantLock() {
    sync = new NonfairSync();
    }

    2.传入参数 true则为公平锁 public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    }

    二。lock方法解读:


    (非公平锁的lock方法) final void lock() {
    if (compareAndSetState(0, 1))
    setExclusiveOwnerThread(Thread.currentThread());
    else
    acquire(1);
    }
    unsafe的compareAndSwapInt方法是native的.
    compareAndSetState(0, 1) 尝试获取锁,把state的状态从0改为1表示获取锁,setExclusiveOwnerThread这个方法是设置获取锁的线程为当前线程。

    如果获取所失败,acquire(1)

    public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
    acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
    selfInterrupt();
    }


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

    final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState(); //获取当前state的值
    if (c == 0) { //如果当前的值为0,也就是说有获取锁的线程释放了锁,然后类似lock方法获取锁
    if (compareAndSetState(0, acquires)) {
    setExclusiveOwnerThread(current);
    return true;
    }
    }
    else if (current == getExclusiveOwnerThread()) { //如果当前线程就是获取锁的线程,那么state+1
    int nextc = c + acquires;
    if (nextc < 0) // overflow
    throw new Error("Maximum lock count exceeded");
    setState(nextc);
    return true;
    }
    return false;
    }


    --------------------
    acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 创建一个node 添加到Node中 有volatile修饰可见
    然后遍历Node

    final boolean acquireQueued(final Node node, int arg) {
    try {
    boolean interrupted = false;
    for (;;) {
    final Node p = node.predecessor();
    if (p == head && tryAcquire(arg)) {
    setHead(node);
    p.next = null; // help GC
    return interrupted;
    }
    if (shouldParkAfterFailedAcquire(p, node) &&
    parkAndCheckInterrupt())
    interrupted = true;
    }
    } catch (RuntimeException ex) {
    cancelAcquire(node);
    throw ex;
    }
    }

    acquireQueued也是个无限循环.就是说要么获取到锁,要么中断当前线程.
    acquireQueued会再次调用tryAcquire,就是再尝试一次获取锁.
    shouldParkAfterFailedAcquire是判断是否要中断当前线程.


    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
    int ws = pred.waitStatus;
    if (ws == Node.SIGNAL)
    return true;
    if (ws > 0) {
    do {
    node.prev = pred = pred.prev;
    } while (pred.waitStatus > 0);
    pred.next = node;
    } else {
    compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
    }
    return false;
    }

    2.unlock方法:

    public void unlock() {
    sync.release(1);
    }

    public final boolean release(int arg) {
    if (tryRelease(arg)) {
    Node h = head;
    if (h != null && h.waitStatus != 0)
    unparkSuccessor(h);
    return true;
    }
    return false;
    }


    protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
    throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
    free = true;
    setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
    }

    从tryRelease可以看到释放锁的条件是:c == 0 就是锁的计数为0;
    unparkSuccessor:释放锁.

    private void unparkSuccessor(Node node) {
    int ws = node.waitStatus;
    if (ws < 0)
    compareAndSetWaitStatus(node, ws, 0);

    Node s = node.next;
    if (s == null || s.waitStatus > 0) {
    s = null;
    for (Node t = tail; t != null && t != node; t = t.prev)
    if (t.waitStatus <= 0)
    s = t;
    }
    if (s != null)
    LockSupport.unpark(s.thread);
    }




  • 相关阅读:
    springclould feign客户端添加全局参数
    mysql单向自动同步
    MongoDB的安装和配置(Windows系统)及遇到的常见问题解答
    电脑中安装多个jdk,eclipse的选择!
    css(外部样式表)中各种选择器(定义属性时)的优先级
    HTML5结合CSS的三种方法+结合JS的三种方法
    HTML5图片居中的问题
    html->html5->css->javascript(js)->jQuery->AJAX->JSON
    自定义方法实现ArrayList排序
    java,while循环的使用,接收用户的输入,进行不同的操作!
  • 原文地址:https://www.cnblogs.com/anxbb/p/8425494.html
Copyright © 2011-2022 走看看