java 并发之锁 锁

  据jvm内存模型,线程共享主存,各变量同步不及时,造成线程不安全,为此java提供了锁来解决线程不安全。

  乐观锁

    从理论上讲,乐观锁假设各线程不同时修改变量,仅仅通过版本号,时间戳去保证线程安全。java提供的CAS(aompareAndSwap)也是乐观锁的一一种实现

    CAS:比较与交换,有3个核心变量,v-内存值,A-期望值,B-修改值,只有当A与v的值相同时才去更新v的值为B,否则不断循环;

       ABA问题,当一个线程把数据修改成了B,然后又修改回了A,此时其他线程读取时,认为变量并没有问题,忽略了修改的过程

for (;;) { //不断自旋
                int wc = workerCountOf(c);//统计工作线程
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))//工作线程通过CAS+1
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
ThreadPoolExecutor中的实现

  悲观锁

    从理论上讲,悲观锁假设各线程同时修改变量,通过加锁,线程独占共享变量去保证线程安全。java提供的synchronized,lock的就是悲观锁的一种实现。

    synchronized

        来自:https://blog.csdn.net/zjy15203167987/article/details/82531772

      jvm底层实现,锁对象,保证只有一个线程进去临界区,同时保证共享变量的可见性;但是锁的粒度太大,太占资源,线程等待时间过长。

      同步实例方法,锁实例对象,只有获取实例对象才能进去,其他线程只能访问非synchronized的方法

      锁静态对象,锁类对象,只有获取类对象才能进去

      同步代码块,锁指定对象,只有获取指定对象的锁才能进去

      

    Lock

      jdk提供的一种实现,锁的粒度小,可控,但需要加锁与释放锁;

      ReentrantLock-可重入锁、独占锁,底层是AQS(AbstractQueuedSynchronizer)同步队列,里面包含的公平与非公平锁的实现     

        详情可见:https://blog.csdn.net/qq_29373285/article/details/85964460

public ReentrantLock(boolean fair) {//true实现公平锁,false非公平锁
        sync = fair ? new FairSync() : new NonfairSync();
    }
static final class FairSync extends Sync {//公平锁实现
    final void lock() {//获取锁的状态,锁未被占用即可进入
            acquire(1);
    }
    public final void acquire(int arg) {//cas获取锁,按顺序加入队列
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {//cas修改锁状态,设置独占锁
                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;
        }
    
}    
公平锁      

      ReadWriteLock-读写锁

        详情可见:https://www.jianshu.com/p/9cd5212c8841