synchronized 关键字是锁的一种实现
class X {
// 修饰非静态方法
// 当修饰非静态方法的时候,锁定的是当前实例对象 this
synchronized void foo() {
// 临界区
}
// 修饰静态方法
// 当修饰静态方法的时候,锁定的是当前类的 Class 对象
synchronized static void bar() {
// 临界区
}
// 修饰代码块
Object obj = new Object();
void baz() {
synchronized(obj) {
// 临界区
// 锁定obj 对象
}
}
}
- 当修饰非静态方法的时候,锁定的是当前实例对象 this
- 当修饰静态方法的时候,锁定的是当前类的 Class 对象
- 当修饰代码块的时候,锁定的是传入的对象
加锁 lock() 和解锁 unlock() 是被 Java 默默加上的,Java 编译器会在 synchronized 修饰的方法或代码块前后自动加上加锁 lock() 和解锁 unlock()
class SafeCalc {
long value = 0L;
synchronized long get() {
return value;
}
synchronized void addOne() {
value += 1;
}
}
把 value 改成静态变量,把 addOne() 方法改成静态方法
class SafeCalc {
static long value = 0L;
synchronized long get() {
return value;
}
synchronized static void addOne() {
value += 1;
}
}
改动后的代码是用两个锁保护一个资源。这个受保护的资源就是静态变量 value,两个锁分别是 this 和 SafeCalc.class
由于临界区 get() 和 addOne() 是用两个锁保护的,因此这两个临界区没有互斥关系,临界区 addOne() 对 value 的修改对临界区 get() 也没有可见性保证,这就会导致并发问题了
class SafeCalc {
long value = 0L;
long get() {
synchronized (new Object()) {
return value;
}
}
void addOne() {
synchronized (new Object()) {
value += 1;
}
}
}
可以用一把锁来保护多个资源,但是不能用多把锁来保护一个资源
用不同的锁对受保护资源进行精细化管理,能够提升性能。叫细粒度锁
- 如果资源之间没有关系,很好处理,每个资源一把锁就可以了。
- 如果资源之间有关联关系,就要选择一个粒度更大的锁,这个锁应该能够覆盖所有相关的资源。
此文章为2月Day15学习笔记,内容来源于学习完极客时间《mysql45讲》后自行拓展,强烈推荐该课程! 开启更多功能,提升办公效能 另外,最近重温操作系统时发现了一个免费精品好课,闪客的《Linux0.11源码趣读》,这个课给我感觉像在用看小说的心态学操作系统源码,写的确实挺牛的,通俗易懂,直指本源,我自己也跟着收获了很多。 这个课在极客时间上是免费的,口碑很不错,看评论下很多人在催更和重温,强烈推荐!
戳此链接领取:time.geekbang.org/opencourse/…
或通过下面海报领取👇🏻!