JAVA锁---------------------CLH锁和MCS锁

       参考:http://ifeve.com/java_lock_see2/

一:CLH锁

  1. 实现
    package com.eden.coreLearn.thread.lock;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    
    import org.junit.Test;
    
    /**
     * CLH自旋锁
     * 
     * @author [email protected] 2016年7月15日 下午5:39:38
     */
    public class CLHLock {
    
        public static class CLHNode {
            private volatile boolean isLocked = true;
        }
    
        @SuppressWarnings("unused")
        private volatile CLHNode tail;
    
        private static final ThreadLocal nodeLocal = new ThreadLocal();
    
        //构建一个CLHLock对象中变量名为tail,类型为CLHNode的原子更新器(该变量必须有volatile关键字修饰)
        private static final AtomicReferenceFieldUpdater updater   = AtomicReferenceFieldUpdater
                .newUpdater(CLHLock.class, CLHNode.class, "tail");
    
        public void lock() {
            CLHNode node = new CLHNode();
            nodeLocal.set(node);
            CLHNode preNode = updater.getAndSet(this, node);
            //        System.out.println(String.format("preNode=%s", preNode));
            if (preNode != null) {
                while (preNode.isLocked) {
    
                }
                preNode = null;
                nodeLocal.set(node);//没看懂为什么又要set一次
            }
        }
    
        public void unlock() {
            CLHNode node = nodeLocal.get();//获取当前线程锁的节点
            if (!updater.compareAndSet(this, node, null)) {
                node.isLocked = false;
            }
            node = null;
        }
    
        @Test
        public void testCLHLock() throws InterruptedException {
            Student st = new Student(new CLHLock());
            for (int i = 0; i < 100; i++) {
                new Thread(new CLHLockThread(st), i + "").start();
            }
            TimeUnit.SECONDS.sleep(30);
        }
    
        public class Student {
            private int     i = 0;
    
            private CLHLock lock;
    
            public Student(CLHLock lock) {
                this.lock = lock;
            }
    
            public void add() {
                lock.lock();
                this.i = this.i + 1;
                System.out.println(String.format("线程%s的变量i=%s", Thread.currentThread().getName(), this.i));
                //            lock.unlock();
            }
        }
    
        public class CLHLockThread extends Thread {
            private Student st;
    
            public CLHLockThread(Student st) {
                this.st = st;
            }
    
            @Override
            public void run() {
                st.add();
            }
        }
    }
    

  2. CLH锁是通过不停的查询前驱变量preNode来实现的,是隐式的队列,并没有真实的后继节点
  3. lock函数实现:调用lock的时候,先新建一个自己的tail node节点,并存到自己的线程栈里,然后通过updater获取共享的tail node并将共享的tail node更新成自己的tail node,如果共享的tail node不为空,则获取锁失败,执行空轮询,反之成功
  4. unlock函数实现,先取出当前线程的tail node节点,并与共享的tail node节点比较,如果相同,则释放锁,同时将共享的tail node更新成null
  5. CLH锁也是公平锁,遵循先来后到的顺序,但是和其他自旋锁一样,竞争激烈时会导致性能下降

二:MCS锁

  1. 实现
    package com.eden.coreLearn.thread.lock;
    
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    
    /**
     *
     * @author [email protected] 2016年7月15日 下午6:36:40
     */
    public class MCSLock {
    
        public class MCSNode {
            private volatile MCSNode next;
            private volatile boolean isLocked = true;
        }
    
        private static final ThreadLocal nodeLocal = new ThreadLocal();
        
        @SuppressWarnings("unused")
        private volatile MCSNode node;
        
        private static final AtomicReferenceFieldUpdater updater   = AtomicReferenceFieldUpdater
                .newUpdater(MCSLock.class, MCSNode.class, "node");
    
        public void lock() {
            MCSNode current = new MCSNode();
            nodeLocal.set(current);
            MCSNode preNode = updater.getAndSet(this, current);
            if (preNode != null) {
                preNode.next = current;
                while (current.isLocked) {
    
                }
            }
        }
    
        public void unlock() {
            MCSNode current = nodeLocal.get();
            if (current.next == null) {
                if (updater.compareAndSet(this, current, null)) {
    
                } else {
                    while (current.next == null) {
    
                    }
                }
            } else {
                current.next.isLocked = false;
                current.next = null;
            }
        }
    
    }
    

  2. 实现其实再CLH锁的基础上加了真实的后继节点
  3. CLHlock是不停的查询前驱变量, 导致不适合在NUMA 架构下使用(在这种结构下,每个线程分布在不同的物理内存区域,MCSLock则是对本地变量的节点进行循环。不存在CLHlock 的问题。

你可能感兴趣的:(java基础,多线程,学习)