本篇说明:

        1. synchronized锁对象

        2. synchronized锁类

        3. synchronized何时不会产生互斥情况,从而不会影响效率。

在Java中用synchronized关键字来标记该对象的synchronized方法或者访问synchronized代码块使用了互斥锁。互斥锁的锁定的目标可能是对象也可能是类。

当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。

在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。

Monitor 是线程私有的数据结构,每一个线程都有一个可用 monitor record 列表,同时还有一个全局的可用列表。每一个被锁住的对象都会和一个 monitor 关联,同时 monitor 中有一个 Owner 字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用。Monitor 是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现的线程同步。

获取对象锁

  • synchronized(this|object) {}
  • 修饰非静态方法

获取类锁

  • synchronized(类.class) {}
  • 修饰静态方法

 1. 非静态方法中,synchronized会占用对象锁

下面看demo:

java 根据对象的参数实现互斥锁_对象锁

java 根据对象的参数实现互斥锁_java 根据对象的参数实现互斥锁_02

结果:

java 根据对象的参数实现互斥锁_对象锁_03

我们可以看到计算结果我设置了2秒延迟,打印设置了1秒,如果没有synchronized,应该是打印两次计算一次,而现在是打印一次计算一次。这就是互斥导致了运行效率降低的原因。

2.静态方法中,synchronized会占用类锁。这个就不加demo了。

3.  synchronized何时不会产生互斥情况,从而不会影响效率

要不产生互斥情况,那么多线程不回同一时间去争取同一把锁。因为同一类的不同实例对象都有与之对应的互斥锁,而静态方法用的是类锁。所以同一个类的不同实例对象、静态方法和非静态方法之间不用考虑互斥。