本篇说明:
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:
结果:
我们可以看到计算结果我设置了2秒延迟,打印设置了1秒,如果没有synchronized,应该是打印两次计算一次,而现在是打印一次计算一次。这就是互斥导致了运行效率降低的原因。
2.静态方法中,synchronized会占用类锁。这个就不加demo了。
3. synchronized何时不会产生互斥情况,从而不会影响效率
要不产生互斥情况,那么多线程不回同一时间去争取同一把锁。因为同一类的不同实例对象都有与之对应的互斥锁,而静态方法用的是类锁。所以同一个类的不同实例对象、静态方法和非静态方法之间不用考虑互斥。