• 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

  • 相关阅读:
    ArcGIS Engine 中的多线程使用
    Arcgis栅格时序地图制作---时间轴动态展示多期影像
    R树空间索引
    R-Tree空间索引算法的研究历程和最新进展分析
    学生表、课程表、 成绩表 、教师表sql练习
    Mysql建表出现1005错误
    MySQL数据类型详解
    数据库操作语句类型(DQL、DML、DDL、DCL)简介
    Spring MVC标签<mvc: annotation-driven />小结 原
    EasyUI Menu 菜单
  • 原文地址:https://www.cnblogs.com/ruerror/p/13676557.html
Copyright © 2020-2023  润新知