深入浅出的多线程

1.悲观锁与乐观锁:悲观的锁就是想到最坏情况,每次去拿数据的时候都会认为该数据会被修改,所以每次拿数据时都会进行阻塞直到其拿到锁,一个线程在使用时其他进入的线程进行阻塞,直到用完后再把资源转让。synchronized和reentrantlock等独占锁都是悲观锁思想。

    乐观锁假设最好的情况,每次去都认为没有上锁,使用版本号机制和CAS算法实现。

    乐观锁适用于多读场景,其中的冲突很少,省去了锁的开销,加大系统的吞吐量。

    悲观锁适用于多写场景,经常发生冲突,降低了性能。

    乐观锁原理:会在数据上添加一个数据版本号,每次对其进行操作时都会读取此版本号,如果进行修改后再次读取此版本号如果和刚开始一致就可以更新,如果不一致就放弃更新,拿取新的版本号继续进入下一个更新操作,直到一致后更新数据,然后将此版本号加一。

    乐观锁的问题:ABA问题:如果当前准备更新时读取到的版本号一致,但此时刚好有另一个操作员读取更新时,两个操作就会发生冲突,导致数据覆盖,不正确。时间开销大:如果一直读取不到一致的版本号,就会一直自旋操作,消耗时间太多。

    Synchronized:线程同步策略,当一个线程在使用数据时,其就会阻塞后面的线程进行排队,

执行完毕后唤醒后面的进程继续执行数据。他的底层实现主要靠lock-tree的队列。基本思路是自旋后阻塞,竞争切换后继续竞争锁,获得了高吞吐量。

2.怎么使用synchronized关键字的:

        1.修饰实例方法,当前对象实例化时加锁,进入代码块时需要获取加的锁

        2.修饰静态方法,对类对象加锁,因为是静态的方法,不属于任何实例对象,所以相当于对当前的类进行加锁。

        3.修饰代码块,对给定的对象及方法加锁,直接用synchronized(对象)、synchronized(类名.class)

3.synchronized底层原理:

        在关键字设计实现时使用的是monitorenter和monitorexit指令,前者指向代码开始位置,后者是结束位置,开始时前者会获取当前代码块的锁,当计数器是0时可以获取到,获取后就+1,后面来的进程如果获取到的值是1就获取失败阻塞,前一个进程进行完毕会将计数器置为0就释放了锁,后面进程更新获取后为0就开始执行。

4.synchronized的方法:

        wait()、notify()、notifyall()等待、通知、通知所有;

5.可重入锁:一个线程在外层获取了锁,但进入该线程内部可直接获取锁;可重入锁在synchrozied和ReentrantLock都可以使用,在获取锁后进入此获取方法中还可以获取锁进行线程做,不同的是synchrozied对于持续获取锁后自动释放,但是ReentrantLock获取了一个锁必须对应着进行释放锁,才能不会死锁,如果外层没有释放,那么内层的进程就获取不到锁从而一直在等待状态。

6.LockSupport:用来创建锁和其他同步类的基本阻塞原语。 其中的park()和unpark()作用分别是阻塞线程和解除阻塞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值