zoukankan      html  css  js  c++  java
  • Java多线程笔记2

    synchronized使用:
    同步代码块
    synchronized(this|任意一个Object子类对象|当前类.class) {

    }

    同步方法

    修饰普通对象方法 锁当前对象this

    修饰类的静态方法 锁当前类.class

    保护的是什么?几个锁?
    使用一把锁锁住了两个毫无关系的对象

    如何保护毫无关系的资源?
    使用多把锁锁住不同的资源

    class Account {
        // 余额
        int sal;
        // 密码
        String password;
        // 余额资源的锁
        private Object salLock = new Object();
        // 密码资源的锁
        private Object passLock = new Object();
        public int getMoney() {
            synchorinzed(salLock) {}
        }
    
        public void setMoney() {
            synchorinzed(salLock) {}
        }
    
        public String getPassword() {
            synchorinzed(passLock) {}
        }
        
        public void setPassword() {
            synchorinzed(passLock) {}
        }
    }

    转账
    A -> B 100
    A -= 100;
    B += 100;
    如何保护有关联关系的对象:
    使用同一把锁

    public void zhuangzhang(Account target) {
        synchroinzed(Account.class) {
            this.sal -= 100;
            target.sal += 100;
        }
    }

    由于转账涉及两个账户间的sal操作,因此需要将两个账户同时锁定。
    由于方法的synchrond只能锁一个对象,因此锁不住转账操作

    这个时候要看synchronized底层实现

    synchronized底层实现:
    在使用synchronized时必须保证锁定对象必须为Object以及其子类对象。
    synchronized使用的是JVM层级别的MonitorEnter与MonitorExit实现。

    这两个指令都必须获取对象的同步监视器Monitor

    对象锁Monitor机制

    monitorenter:
    检查obj对象的Monitor计数器值是否为0,为0表示此监视器还未被任意一个线程获取,此时线程可以进入同步代码块并且将Monitor值+1,将Monitor的持有线程标记为当前线程

    当Monitor计数器值不为0且持有线程不是当前线程,表示Monitor已经被别的线程占用,当前线程只能阻塞等待。

    当Monitor计数器值不为0但是持有线程恰好是当前线程,

    monitorexit:
    Monitor计数器值-1

    可重入锁:
    当执行MonitorEnter时。对象的Monitor计数器值不为0,但是持有线程恰好是当前线程,
    此时将Monitor计数器值再次+1,当前线程继续进入同步方法或代码块,就好比上面第一个代码,我调用getMoney()方法的时候,getMoney()方法里面也可以调用getPassword()方法

    CAS操作(无锁实现的同步-乐观锁)-自旋

    class Test {
        int i = 0;
    // 线程1
        synchronized(this) {
            i = 10;
        }
    }    

    CompareAndSwap(O,V,N)
    O:当前线程存储的变量值 0
    V:内存中该变量的具体值 10
    N:希望修改后的变量值 10

    当O==V时,此时表示还没有线程修改共享变量的值,此时可以成功的将内存中的值修改为N

    当O!=V时,表示此时内存中的共享变量值已被其他线程修改,此时返回内存中的最新值V,再次尝试修改变量

    线程挂起阻塞:车熄火
    自旋:脚踩刹车,车不熄火

    1.ABA问题:
    解决ABA问题添加版本号

    2.自旋在CPU上跑无用指令,会浪费CPU资源
    自适应自旋
    JVM尝试自旋一段时间,若在此时间内,线程成功获取到锁,再下次获取锁时,适当延长自旋时间。
    若在此时间内,线程没有获取到锁,再下次获取锁时,适当缩短自旋时间。

    3.公平性问题
    处于阻塞态线程可能会一直无法获取到锁
    Lock锁可以实现公平性,synchronized无法实现公平锁

    偏向锁:JDK1.6之后默认synchronized
    最乐观的锁:进入同步快或同步方法的始终是一个线程

    当出现另一个线程也尝试获取锁(在不同时刻)时,偏向锁会升级为轻量级锁


    轻量级锁
    不同时刻有不同的线程尝试获取锁,"量黄灯策略"

    同一时刻有不同线程尝试获取锁,会将偏向锁升级为重量锁

    重量级锁
    JDK1.6之前synchronized都是重量级锁,将线程阻塞挂起(JDK1.6自适应自旋)

    锁只有升级过程没有降级过程

    锁粗化

    当出现多次连续的加锁与解锁过程,会将多次加减锁过程粗化为一次的加锁与解锁过程

    死锁:
    死锁产生条件:以下四种条件同时满足才会导致死锁
    1.互斥
    共享资源只能同时被一个线程占用
    2.占用且等待
    3.不可抢占
    线程T1拿到了资源X的锁,其他线程不能抢占X锁
    4.循环等待
    线程T1拿到了资源X的锁,去申请Y的锁
    线程T2拿到了资源Y的锁,去申请X的锁

  • 相关阅读:
    webpack打包加大就是为了加大文件允许体积,提升报错门栏
    webpack打包配置服务
    webpack 打包 js图片
    webpack 打包css 图片
    webpack打包多个html打包,分别引入不同的 多个 js 文件 流程
    webpack打包所有css打包压缩到一个js里面
    webapck 打包多个 js ,多个 html 同时打包流程
    webpack打包多个js 合并成默认 main.js文件步骤
    wbpack打包准备工作
    模拟攒机小程序 兼容提示 电源功率推荐 小白攒机神器
  • 原文地址:https://www.cnblogs.com/du001011/p/11001177.html
Copyright © 2011-2022 走看看