跳至主要內容
轻量级锁

1、轻量级锁

锁撤销升级为轻量级锁之后,那么对象的Markword也会进行相应的的变化。

下面先简单描述下锁撤销之后,升级为轻量级锁的过程:

a) 线程在自己的栈桢中创建锁记录 LockRecord。
 b) 将锁对象的对象头中的MarkWord复制到线程的刚刚创建的锁记录中。
 c) 将锁记录中的Owner指针指向锁对象。
 d) 将锁对象的对象头的MarkWord替换为指向锁记录的指针。

2、锁消除

由于偏向锁失效了,那么接下来就得把该锁撤销,锁撤销的开销花费还是挺大的,其大概的过程如下:


zheng大约 1 分钟java基础
偏向锁

0、从偏向锁到重量锁

在java同步代码快中,synchronized的使用方式无非有两个 :   

1)通过对一个对象进行加锁来实现同步
synchronized(lockObject){
     //代码
 }

zheng大约 4 分钟java基础
公平锁、非公平锁

1、概念:

    公平锁:加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得。
    公平所:线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。

    更多的是直接使用非公平锁:非公平锁比公平锁性能高5-10倍,因为公平锁需要在多核情况下维护一个队列,如果当前线程不是队列的第一个无法获取锁,增加了线程切换次数。

    原理 : https://www.cnblogs.com/little-fly/p/10365109.html

    https://www.jianshu.com/p/06340f8feb05

zheng小于 1 分钟java基础
悲观锁、乐观锁

1、悲观锁

假设会发生并发冲突,屏蔽一切可能违反数据完整性的操作(具有强烈的独占和排他性)

       依赖数据库的锁机制实现,以保证操作最大程度的独占性。

 百度百科:正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

2、缺点


zheng大约 4 分钟数据库mysql
互斥锁

1、关于“互斥”和“同步”的概念

互斥 : 就是线程A访问了一组数据,线程BCD就不能同时访问这些数据,直到A停止访问了
同步 : 就是ABCD这些线程要约定一个执行的协调顺序,比如D要执行,B和C必须都得做完,而B和C要开始,A必须先得做完。

互斥 :就是不同线程通过竞争进入临界区(共享的数据和硬件资源),为了防止访问冲突,在有限的时间内只允许其中之一独占性的使用共享资源。如不允许同时写

同步 :关系则是多个线程彼此合作,通过一定的逻辑关系来共同完成一个任务。一般来说,同步关系中往往包含互斥,同时对临界区的资源会按照某种逻辑顺序进行访问。如先生产后使用


zheng大约 2 分钟java基础
读写锁

4、读写锁

1、读写锁介绍:

    ReadWriteLock同Lock一样也是一个接口,提供了readLock和writeLock两种锁的操作机制,一个是只读的锁,一个是写锁。 

    理论上,读写锁比互斥锁允许对于共享数据更大程度的并发。与互斥锁相比,读写锁是否能够提高性能取决于读写数据的频率、读取和写入操作的持续时间、以及读线程和写线程之间的竞争。 

    一些业务场景中,大部分 只是读数据,写数据很少,如果仅仅是读数据的话并不会影响数据正确性(出现脏读),而如果在这种业务场景下,依然使用独占锁的话,很显然这将是出现性能瓶颈的地方。 针对这种读多写少的情况,java还提供了另外一个实现Lock接口的ReentrantReadWriteLock(读写锁)。读写所允许同一时刻被多个读线程访问,但是在写线程访问时,所有的读线程和其他的写线程都会被阻塞。



    读-读能共存,
     读-写不能共存,
     写-写不能共存。 

zheng大约 5 分钟java基础
可重入锁

1、可重入锁:

也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。
"独占",就是在同一时刻只能有一个线程获取到锁,而其它获取锁的线程只能处于同步队列中等待,只有获取锁的线程释放了锁,后继的线程才能够获取锁。

“可重入“,就是支持重进入的锁,它表示该锁能够支持一个线程对资源的重复加锁。

在JAVA环境下 ReentrantLock 和synchronized 都是可重入锁。

2、Synchronized和ReentrantLock

1)性能区别:


zheng大约 3 分钟java基础
阻塞锁

阻塞锁

1、阻塞锁优势

与自旋锁不同,改变了线程的运行状态。

在JAVA环境中,线程Thread有如下几个状态:
  1. 新建状态

  2. 就绪状态

  3. 运行状态

  4. 阻塞状态

  5. 死亡状态

    阻塞锁,可以说是让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。
    JAVA中,能够进入 / 退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait() / notify() ,LockSupport.park() / unpart()


zheng大约 3 分钟java基础
自旋锁

自旋锁

1、自旋锁概念(spinlock)

是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting。

2、自旋锁的优点 :

自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是active的;不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快非自旋锁在获取不到锁的时候会进入阻塞状态,从而进入内核态,当获取到锁的时候需要从内核态恢复,需要线程上下文切换。 (线程被阻塞后便进入内核(Linux)调度状态,这个会导致系统在用户态与内核态之间来回切换,严重影响锁的性能)


zheng大约 3 分钟java基础