Java锁原理与应用

一、锁

  锁是一种互斥的机制,在多线程环境中实现对资源的协调与控制,凡是有资源被多线程共享,涉及到修改的情况就要考虑锁的加持。

(0)Java锁原理

  0)引申:Java对象结构

    Java对象结构分为3部分:

    ①对象头(包括:Mark Word(存储了当前对象运行时的状态信息,如HashCode、指向锁记录的指针等)、Class Pointer(指针,指向当前对象类型所在方法区中的Class信息));

   如图,MarkWord结构(jdk1.8)

HotSpot 64位操作系统(一个对象的markWord在内存占用8字节)

锁标志位,分别代表无锁、偏向锁、轻量级锁、重量级锁4种状态;

   ②实例数据;

   ③对齐填充字节(在内存中占8字节)。

1)在Java中,每个对象都拥有一把锁,存放在对象头中,记录了当前对象被哪个线程占用。

  2)操作系统用户态和内核态

    由于需要限制不同的程序之间的访问能力,防止他们获取别的程序的内存数据,或者获取外围设备的数据,并发送到网络,CPU划分出两个权限等级,用户态和内核态。所有用户程序都是运行在用户态的,当程序需要做一些内核态的事情,,例如从硬盘读取数据,,或者从键盘获取输入等。而唯一可以做这些事情的就是操作系统,此时程序就需要操作系统请求以程序的名义来执行这些操作,即将用户态程序切换到内核态。

    内核态: CPU可以访问内存所有数据,,包括外围设备, 例如硬盘,、网卡, CPU也可以将自己从一个程序切换到另一个程序。

    用户态: 只能受限的访问内存,且不允许访问外围设备.,占用CPU的能力被剥夺。

(1)锁的实现方式

0)引申:

    在java中,锁的实现主要采用两种方式:1、基于Object的悲观锁;2、基于CAS的乐观锁,Lock接口是基于CAS原理实现。java5之前的版本只有synchronized锁,基于操作系统提供的指令,在内核态实现多线程之间访问资源的同步性;之后发现基于内核态的synchronize的锁开销很大,提出了Lock锁机制,在java5版本中被官方采纳;随后java官方对synchronized进行了优化,提出了对象锁的4种状态概念。在java的后续版本中,两者在性能上差别需要根据实际情况进行选择使用。

  1)synchronized

    j.u.c.Locks中说明synchronized是在硬件层面依赖特殊的CPU指令。synchronized别编译后会生成monitorenter和monitorexit两个字节码指令,依赖这两个字节码指令进行线程同步。monitor,监视器(管程),一旦线程进入了monitor,那么其他线程只能等待,只有当这个线程退出,其他线程才有机会进入。monitor依赖于操作系统的Mutex Lock实现,所以每当挂起或唤醒线程,都要切换到操作系统的内核态,这个操作比较重量级。在某些情况下,甚至于切换时间本身就会超出线程执行任务的时间。java6开始,对synchronized进行了优化,引入了对象锁的4种状态,分别是无锁、偏向锁、轻量级锁、重量级锁。

eg:

public class SynchronizedDemo {
    public void method() {
        synchronized (this) {
            System.out.println("Method 1 start");
        }
    }
}

对以上示例代码执行javap -p -c 指令(说明,javap <---> java class文件分解器, -p <-----> 展示所有的类和成员, -c <-------> 对代码进行反编译, 具体指令说明可通过javap -help 展示)

synchronized特点:

  ①支持线程可重入;

  ②等待状态(前一个线程并未释放锁,当前线程处于不断尝试获取锁的状态(对应java中定义的RUNNABLE状态))不可中断;

  ③synchronized会自动释放锁;

  ④synchronized是非公平锁;

  ⑤synchronized既可以锁住代码块,也可以锁住方法;

  注:java中定义了线程执行的的6种状态

    1.创建 2. 执行 3.销毁 4.时间限制的等待 5.无线等待 6.阻塞

操作系统中定义的线程状态有3种:运行态、阻塞态、就绪态;线程的生命周期在此基础上添加了创建和销毁;

  2)Lock接口

    Lock接口提供了区别于synchronized的另一种具有方法操作的同步方式,支持更多灵活的结构,可以关联多个Condition(java提供的用户线程通信的接口)对象。

package lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class RetreenLockTest {

    private static Lock rl = new ReentrantLock();

    private static void testReentrantLock(){
        Runnable run = ()->{
 
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值