zoukankan      html  css  js  c++  java
  • Synchronized && Lock

    想要详细学习synchronized的同学们可以看 http://www.cnblogs.com/noKing/p/9190673.html

    本文参考:  http://www.cnblogs.com/dolphin0520/p/3923167.html

    https://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1

    介绍一下Lock接口

    java.util.concurrent.locks包中,有三个接口Lock,ReadWriteLock,Condition,常用到的类有ReentrantLock(实现了Lock接口),ReentrantReadWriteLock(实现了ReadWriteLock接口)

    Lock.java

    public interface Lock {
    
        /**
         * 获取锁,如果锁被暂用,则一直等待
         */
        void lock();
    
        /**
         * 获取锁,如果在获取锁阶段进入了等待,可以中断此线程
         *
         * @throws InterruptedException
         */
        void lockInterruptibly() throws InterruptedException;
    
        /**
         * 获取锁,如果获取成功返回true,如果获取失败返回false
         *
         * @return
         */
        boolean tryLock();
    
        /**
         * 获取锁,如果在time时间内获得锁,就返回true;否则返回false
         *
         * @param time
         * @param unit
         * @return
         * @throws InterruptedException
         */
        boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    
        /**
         * 释放锁
         */
        void unlock();
    
        /**
         * Returns a new {@link Condition} instance that is bound to this
         * {@code Lock} instance.
         * <p>
         * <p>Before waiting on the condition the lock must be held by the
         * current thread.
         * A call to {@link Condition#await()} will atomically release the lock
         * before waiting and re-acquire the lock before the wait returns.
         * <p>
         * <p><b>Implementation Considerations</b>
         * <p>
         * <p>The exact operation of the {@link Condition} instance depends on
         * the {@code Lock} implementation and must be documented by that
         * implementation.
         *
         * @return A new {@link Condition} instance for this {@code Lock} instance
         * @throws UnsupportedOperationException if this {@code Lock}
         *                                       implementation does not support conditions
         */
        Condition newCondition();
    }  

    ReentrantLock.java
    public class ReentrantLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = 7373984872572414699L;
    
        private final Sync sync;
    
    
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860L;
    
            /**
             * Performs {@link Lock#lock}. The main reason for subclassing
             * is to allow fast path for nonfair version.
             */
            abstract void lock();
    
            /**
             * Performs non-fair tryLock.  tryAcquire is implemented in
             * subclasses, but both need nonfair try for trylock method.
             */
            final boolean nonfairTryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        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;
            }
    
            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;
            }
    
            protected final boolean isHeldExclusively() {
                // While we must in general read state before owner,
                // we don't need to do so to check if current thread is owner
                return getExclusiveOwnerThread() == Thread.currentThread();
            }
    
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
    
            // Methods relayed from outer class
    
            final Thread getOwner() {
                return getState() == 0 ? null : getExclusiveOwnerThread();
            }
    
            final int getHoldCount() {
                return isHeldExclusively() ? getState() : 0;
            }
    
            final boolean isLocked() {
                return getState() != 0;
            }
    
            /**
             * Reconstitutes the instance from a stream (that is, deserializes it).
             */
            private void readObject(java.io.ObjectInputStream s)
                    throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                setState(0); // reset to unlocked state
            }
        }
    
        /**
         * 非公平锁
         */
        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * Performs lock.  Try immediate barge, backing up to normal
             * acquire on failure.
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
    
        /**
         * 公平锁
         */
        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            final void lock() {
                acquire(1);
            }
    
            /**
             * Fair version of tryAcquire.  Don't grant access unless
             * recursive call or no waiters or is first.
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (!hasQueuedPredecessors() &&
                            compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                } else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }
    
        /**
         * ReentrantLock默认是非公平锁
         */
        public ReentrantLock() {
            sync = new NonfairSync();
        }
    
        /**
         * ReentrantLock可以通过构造器设定公平锁或者非公平锁
         * @param fair
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    
        /**
         * 获取锁
         * 获取不到就一直处于等待状态
         */
        public void lock() {
            sync.lock();
        }
    
        /**
         * 获取锁
         * 在获取锁时,如果处于等待状态可以将线程中断,结束等待状态
         * @throws InterruptedException
         */
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
    
        /**
         * 获取锁
         * 如果获取成功则返回true,如果获取失败则返回false
         * @return
         */
        public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
        }
    
        /**
         * 获取锁,如果在指定时间内获取成功则返回true,否则返回false
         * @param timeout
         * @param unit
         * @return
         * @throws InterruptedException
         */
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
    
    
        /**
         * 释放锁
         */
        public void unlock() {
            sync.release(1);
        }
    
    
        public Condition newCondition() {
            return sync.newCondition();
        }
    
    
        public int getHoldCount() {
            return sync.getHoldCount();
        }
    
        /**
         * 判断是否被当前线程获取了
         * @return
         */
        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }
    
        /**
         * 判断是否被任何线程获取了
         * @return
         */
        public boolean isLocked() {
            return sync.isLocked();
        }
    
        /**
         * 判断是否是公平锁
         * @return
         */
        public final boolean isFair() {
            return sync instanceof FairSync;
        }
    
    
        protected Thread getOwner() {
            return sync.getOwner();
        }
    
        /**
         * 判断是否有线程在等待当前锁
         * @return
         */
        public final boolean hasQueuedThreads() {
            return sync.hasQueuedThreads();
        }
    
        /**
         * 判断thread是否在等待当前锁
         * @param thread
         * @return
         */
        public final boolean hasQueuedThread(Thread thread) {
            return sync.isQueued(thread);
        }
    
        /**
         * 获取等待队列的长度
         * @return
         */
        public final int getQueueLength() {
            return sync.getQueueLength();
        }
    
    
        protected Collection<Thread> getQueuedThreads() {
            return sync.getQueuedThreads();
        }
    
    
        public boolean hasWaiters(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject) condition);
        }
    
    
        public int getWaitQueueLength(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject) condition);
        }
    
    
        protected Collection<Thread> getWaitingThreads(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject) condition);
        }
    
    
        public String toString() {
            Thread o = sync.getOwner();
            return super.toString() + ((o == null) ?
                    "[Unlocked]" :
                    "[Locked by thread " + o.getName() + "]");
        }
    }
    

      

    ReadWriteLock.java

    public interface ReadWriteLock {
        /**
         * 获取写锁
         */
        Lock readLock();
    
        /**
         * 获取读锁
         */
        Lock writeLock();
    }
    
    ReentrantReadWriteLock.java 源码太长,关于ReentrantReadWriteLock类感兴趣的朋友可以自行查阅API文档。
    ReentrantReadWriteLock允许多线程读,而只允许一个线程写
    但是synchronized只允许获取当前锁的线程读,所以对于多线程读而言,没有ReentrantReadWriteLock性能好

       不过要注意的是,如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。

     如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。

    synchronized 和 Lock区别

    1.Lock是一个接口,一个基于对象的锁;而synchronized是Java中的关键字,synchronized是内置的语言实现,一个基于代码块的锁;

    2.synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致锁泄露;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成锁泄露,因此使用Lock时需要在finally块中释放锁;

    3.synchronized申请与释放只能在一个方法内进行,而Lock支持在一个方法内申请锁,在另一个方法内释放锁。

    4.Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

    5.通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

    6.锁的种类

       可重入锁  可中断锁  公平锁  读写锁
         Lock    true    true   true   true
    Synchronized    true    false   false   false

    7.显示锁提供了一些接口,可以对锁的相关信息进行监控,而内部锁不支持这种特性。ReentrantLock中定义的方法isLocked()可用于检测相应锁是否被某个线程持有,getQueueLength()方法可用于检查相应锁的等待线程的数量。

    锁的选择

    保守策略:默认情况下选用内部锁,仅在需要显示锁所提供的特性时才选用显示锁。

  • 相关阅读:
    windows用户管理与远程管理
    Linux之基础网络配置
    linux之程序包管理
    linux之特殊权限
    设计模式学习笔记——Prototype原型模式
    设计模式学习笔记——Visitor 访问者模式
    XXX is not a function
    终于决定要开始写自己的博客了,先Mark一下
    element ui 与vue跨域通信操作 和框架语法,contentype
    跨域与版本控制
  • 原文地址:https://www.cnblogs.com/Hangtutu/p/9200665.html
Copyright © 2011-2022 走看看