多线程的同步问题


解决线程安全问题

synchronized实现同步处理(加锁处理)

同步代码块

方法中使用synchronized(对象),一般可以锁定当前对象this
表示同一时刻只有一个线程能够进入同步代码块,但是多个线程可以同时进入方法。
同步代码块演示

同步方法

方法声明上加synchronized,表示此时只有一个线程能够进入同步代码块。

同步方法演示

synchronized对象锁概念

synchronized(this)以及普通的synchronized方法只能防止多个线程同时执行同一对象的同步段。也就是说,synchronized锁的是括号里的对象而非代码

全局锁锁代码段
1.使用类的静态同步方法
static synchronized.此时锁得是当前使用的类而非对象
2.在同步代码块中锁当前的class对象
syncjronized(类名称.class){}

synchronized锁多个对象

synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一对象的同步代码段,即synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this.
解决
1.锁住同一个对象。synchronized(this).
2.让synchronized锁这个类对应的class对象–全局锁–synchronized(类名.class)

在这里插入图片描述

synchronized底层原理-monitor机制

使用synchronized进行同步的关键必须要对对象的监视器monitor进行获取,当线程获取到monitor后才能继续往下执行,否则就只能等待。而这个获取的过程是互斥的,即同一时刻只有一个线程能够获取到monitor

执行同步代码块之前首先要先执行monitorenter指令,尝试获取对象的监视器monitor对象,退出的时候执行monitorexit指令。一个monitorenter多个monitorexit?Java虚拟机为了确保所获得的锁在正常执行路径以及异常执行路径上都能够被解锁。
当使用synchronized标记方法时字节码会出现一个ACC_SYNCHRONIZED标记,该标记表示在进入该方法时,JVM需要进行monitorenter操作尝试获取对象的监视器monitor对象,获取成功就继续操作获取失败就等待。在退出该方法时,无论是否正常返回,JVM均需要进行JVM操作。
monitor操作
1.当JVM执行monitorenter时,如果目标对象monitor计数器为0,表示此时该对象没有被其他线程持有(不为0要等待),此时JVM会将锁对象的持有线程置为当前线程,并将monitor计数器+。
2.在目标锁对象不为0的情况下:
2.1如果持有锁对象的线程是当前线程,JVM会将计数器继续+1.(可重入)
2.2否则需要等待,直到持有线程释放锁。
3.当执行monitorexit时,JVM需将锁对象的计数器-1,当计数器减为0,代表该锁已被释放掉,唤醒所有正在等待的线程去竞争该锁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值