线程锁的总结,以及流程

Synchronized锁的只能是引用类型不能是基本类型

锁的时间:当代码块执行完成之后,锁自动释放

锁的定义:对资源进行一个标记,当此资源变为锁住的状态时,其他线程就无法访问这个资源

当线程调度到其他时间片上时,这个锁的状态不会丢,其他线程依旧无法访问这个资源

线程的执行顺序是随机的,放在第一个的有很大概率第一个执行,但不一定

问题:当两个线程之间隔着一些普通功能的代码,那么排在前面的线程与排在后面的线程的执行顺序也还是随机的吗,换而言之,是不是线程的代码的优先级大于非线程的优先级,t1.start()>普通功能代码

个人答案:主线程肯定是最先执行的,因此并不是所有的线程同步执行

举一个死锁的例子

答案:

public class DeadLockDemo {
    private static String A = "A";
    private static String B = "B";
    public static void main(String[] args) {
        new Test().deadLock();
    }
    private void deadLock() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        Thread.currentThread().sleep(2000);
                }catch (InterruptedException e) { e.printStackTrace();
                    }
                    synchronized (B) { System.out.println("1"); } } } });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() { synchronized (B) {
                synchronized (A) {
                    System.out.println("2"); } } } });
        t1.start();
        t2.start();
    }
 }

补充:先执行t2可能不会出现死锁

如何避免死锁

  • 避免一个线程同时获取多个锁

  • 避免一个线程再锁内同时占用多个资源,尽量vaoz每个锁只占一个资源

  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁

  • 对于数据库锁,加锁和解锁必须在同一个数据库的连接里否则会出现锁失败的情况

线程的可见性:每个线程在对数据进行修改时,都有一个副本数据,在多线程的情况下,一个线程修改了变量,其他使用这个变量的线程可以立即获得这个修改之后的数据

volatile比synchronized使用和执行成本更低,不会增加调度和上下文切换,被他修饰的数据,可读不可写,例如,t1,t2线程对同一个资源进行了获取,t1使用了volatile,t1对数据进行了修改,t2则读取的数据无效,需要重新读取

内存屏障:是一组处理器指令,用于实现对内存操作的顺序限制,即通过一些规则,使内存操作有序

缓冲行:缓存中可以分配的最小的存储单位

原子操作:要么都成功,有不成功的则回滚到执行前

缓存行的填充:单个数据占满整个缓冲行,总线不会被阻塞,可以更快的被读取

缓存:在内存和磁盘之间存在一些存储空间,在里面存放一些常用的地址,当需要查找时,先从这里面中获得,没有再从磁盘中查找,缓存的数据有滞后性

缓存命中:在缓存中读取到想要的数据

写命中:当处理器将操作数写回到一个内存缓存的区域时,他首先会检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存

写缺少:一个有效的缓存行写入到不存在的内存区域,举例,当一个线程将那块内存区域标志为无效,而另一个线程则从缓存中获取数据往那块区域写

缓存往外部写的时候,一定是先传地址再传数据

锁总线的意思是,一个进程的全部指令执行完成之后才能进行其他进程的指令

锁缓存:就是给缓存加锁,当有数据经总线往外写时,其他缓存不允许进行修改

Java中的每一个对象都可以作为锁,具体表现形式为:

  • 对于普通方法,锁是当前实例对象

  • 对于静态方法,锁是当前类的Class对象

  • 对于同步代码块,锁是Synchronized括号里配置的对象

    Synchronized用的锁是存在Java对象头里的,数组类型用三个字宽存储对象头,非数组则用两个字宽存储对象头。

锁一共有4种状态,级别从低到高依次是:无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态

锁标志位00表示轻量级锁,10表示重量级锁,11表示GC标记,要被回收利用,01即表示偏向锁,也表示无锁,区分方法是偏向锁位,1是偏向锁,0表示无锁

锁可以升级但是不可以降级,目的是为了提高获得锁和释放锁的效率

优点缺点适用场景
偏向锁加锁和解锁不需要额外的消耗,和执行非同步方法相比仅存在纳秒级的差距如果线程存在竞争,会带来额外的锁撤销的消耗只有一个线程访问同步块场景
轻量级锁竞争的线程不会阻塞,提高了程序的相应速度如果始终得不到锁竞争的线程,使用自旋会消耗CPU追求响应时间,同步块执行速度非常快
重量级锁线程竞争不使用自旋,不会消耗CPU线程阻塞,响应时间缓慢追求吞吐量,同步块执行速度较长

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值