ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深入浅出的多线程

2021-09-15 21:58:26  阅读:99  来源: 互联网

标签:加锁 synchronized 版本号 深入浅出 阻塞 获取 线程 多线程


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()作用分别是阻塞线程和解除阻塞

标签:加锁,synchronized,版本号,深入浅出,阻塞,获取,线程,多线程
来源: https://blog.csdn.net/weixin_43890463/article/details/120317963

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有