synchronized详解

目录

1 简介

2 用法

3 原理

3.1 Monitor对象

3.2 对象的内存布局

3.2.1 对象头

 3.2.2 实例数据

3.2.3 对齐填充

4 synchronized优化

4.1 偏向锁

 偏向锁撤销

 4.2 轻量级锁

 4.3 重量级锁

 4.4 锁粗化

4.5 锁消除

5 锁对比

1 简介

java语言的关键字,在多线程情况下,可以保证共享资源的安全性,保证同一时刻只有一个线程去访问这个共享资源,其他线程必须等待获取该共享资源的线程执行完毕,才能获取到这个资源。synchronized是非公平的,谁先抢到谁使用。

举个例子:火车站窗口卖票(一个窗口),同一时刻只有一个能去买票,其他人必须等到前一个人买完之后离开才能继续买票,而且卖票的服务人员能时刻知道票的剩余量, 不会出现多卖的情况。

2 用法

synchronized能用到两个地方:

(1):作用到代码块,锁定的是当前变量

public void m1() {
        synchronized(o) {
            //业务逻辑
        }
    }

(2):作用到方法上,此时又有两种情况

               ①:实例方法:锁定的是当前对象

    public synchronized void m1(){
          //业务逻辑

    }

               ②:静态方法:锁定的是当前类对象

    public synchronized static  void m1(){
        //业务逻辑

    }

下面是例子:

锁定的对象只有一个线程能够获取,其他线程阻塞等待。下面举例说明:

public class SynTest {
    static Object object =new Object();
    public static void main(String[] args)  {
        new Thread(()->{
                synchronized (object){
                    System.out.println(Thread.currentThread().getName()+"获取了线程111");
                    try {
                        Thread.sleep(5000);
                        System.out.println(Thread.currentThread().getName()+"释放线程");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        }).start();

        new Thread(()->{
            System.out.println("我已经开启线程");
            synchronized (object){
                System.out.println(Thread.currentThread().getName()+"获取了线程222");
            }
        }).start();

    }
}

结果如下:

 说明:Thread-0和Thread-1开始运行,但是由于Thread-0已经把object对象锁定,所以Thread-1只有等到Thread-0线程执行完毕才能得到object对象。

3 原理

在讲述原理之前,先聊聊Monitor对象和对象的内存布局。

3.1 Monitor对象

在HotSpot虚拟机中,Monitor是基于C++ObjectMonitor类实现的,每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

monitor是线程私有的数据结构,每一个线程都有一个可用monitor列表,同时还有一个全局的可用列表,先来看monitor的内部:

Owner:初始时为NULL表示当前没有任何线程拥有该monitor,当线程成功拥有该锁后保存线程唯一标识,当锁被释放时又设置为NULL;

EntryQ:关联一个系统互斥锁(semaphore),阻塞所有试图锁住monitor失败的线程。

RcThis:表示blocked或waiting在该monitor上的所有线程的个数。

Nest:用来实现重入锁的计数。

Hash

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值