• 各类锁(互斥锁,自旋锁,读写锁,乐观锁,悲观锁,死锁)


    互斥锁

    当有一个线程要访问共享资源(临界资源)之前会对线程访问的这段代码(临界区)进行加锁。如果在加锁之后没释放锁之前其他线程要对临界资源进行访问,则这些线程会被阻塞睡眠,直到解锁,如果解锁时有一个或者多个线程阻塞,那么这些锁上的线程就会变成就绪状态,然后第一个变为就绪状态的线程就会获取资源的使用权,并且再次加锁,其他线程继续阻塞等待。

    读写锁

    也叫做共享互斥锁,读模式共享,写模式互斥。有点像数据库负载均衡的读写分离模式。它有三种模式:读加锁状态,写加锁状态和不加锁状态。简单来说就是只有一个线程可以占有写模式的读写锁,但是可以有多个线程占用读模式的读写锁。
    当写加锁的模式下,任何线程对其进行加锁操作都会被阻塞,直到解锁。
    当在读加锁的模式下,任何线程都可以对其进行读加锁的操作,但所有试图进行写加锁操作的线程都会被阻塞。直到所有读线程解锁。但是当读线程太多时,写线程一直被阻塞显然是不对的,所以一个线程想要对其进行写加锁时,就会阻塞读加锁,先让写加锁线程加锁

    自旋锁

    自旋锁和互斥锁很像,唯一不同的是自旋锁访问加锁资源时,会一直循环的查看是否释放锁。这样要比互斥锁效率高很多,但是只会占用CPU。所以自旋锁适用于多核的CPU。但是还有一个问题是当自旋锁递归调用的时候会造成死锁现象。所以慎重使用自旋锁。

    乐观锁

    这其实是一种思想,当线程去拿数据的时候,认为别的线程不会修改数据,就不上锁,但是在更新数据的时候会去判断以下其他线程是否修改了数据。通过版本来判断,如果数据被修改了就拒绝更新,之所以叫乐观锁是因为并没有加锁。

    乐观锁的实现机制CAS

    CAS理解类似于事务:全称Compare And Swap(比较与交换),解决多线程并行情况下使用锁造成性能损耗的一种机制。

    处理器 CAS 指令(内存地址V, 旧值, 新值)

    CAS的原理:

    利用现代处理器都支持的CAS的指令,循环这个指令,直到成功为止.

    CAS原理流程图如下:

    CAS相关的问题:

    • ABA问题:在乐观锁期间,另一个线程修改old value值为new value值,然后又把new value值重新修改为old value.
      • ABA解决方案:加版本号
        • AtomicMarkableReference 可以解决,使用boolean变量——表示引用变量是否被更改过,不关心中间变量变化了几次
        • AtomicStampedReference 也可以解决,其中的构造方法中initialStamp(时间戳)用来唯一标识引用变量,引用变量中途被更改了几次
    • 开销问题:CAS在一直拿不到锁时会一直循环,耗费CPU,造成资源上的浪费
    • 只能保证一个共享变量的原子操作:在内存中 get() 变量时,只能get出一个变量
      • 取巧解决方案:把两个变量封装成一个 

    悲观锁

    当线程去哪数据的时候,总以为别的线程会去修改数据,所以它每次拿数据的时候都会上锁,别的线程去拿数据的时候就会阻塞。
    这两种锁一般用于数据库,当一个数据库的读操作远远大于写的操作次数时,使用乐观锁会加大数据库的吞吐量。

  • 相关阅读:
    Oracle常用命令大全(很有用,做笔记)
    表格驱动编程在代码中的应用
    mac 利用svn下载远程代码出现Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.
    FAILURE: Build failed with an exception.
    There is an internal error in the React performance measurement code.Did not expect componentDidMount timer to start while render timer is still in progress for another instance
    react native TypeError network request failed
    Android向系统相册中插入图片,相册中会出现两张 一样的图片(只是图片大小不一致)
    react-native Unrecognized font family ‘Lonicons’;
    react-native SyntaxError xxxxx/xx.js:Unexpected token (23:24)
    Application MyTest has not been registered. This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.
  • 原文地址:https://www.cnblogs.com/mjtabu/p/11940028.html
Copyright © 2020-2023  润新知