synchronized 关键字
修饰静态方法:定的是当前类的 Class 对象
class Clz {
// 修饰静态方法
synchronized static void m() {}
// 上面相当于
synchronized(X.class) static void m() {}
}
修饰非静态方法:锁定的是当前实例对象 this
class Clz {
// 修饰静态方法
synchronized void m() {}
// 上面相当于
synchronized(this) void m() {}
}
修饰代码块:锁定指定对象
class Clz {
// 修饰代码块
Object obj = new Object();
void m() {
// 锁定 obj 对象
synchronized(obj) {
// 代码块
}
}
}
思考题 1
class Test {
long value = 0L;
// get 方法的 synchronized 关键字是必须的吗?
synchronized long get() {
return value;
}
synchronized void add() {
value += 1;
}
}
如 get 方法不加 synchronized 关键字,就意味着 get 方法没受管程约束。不能保证访问 value 变量的可见性。所以不是线程安全的。所以synchronized 关键字是必须的。
思考题 2
// 通过下面源码画出锁的对应关系
class Test {
static long value = 0L;
synchronized long get() {
return value;
}
synchronized static void add() {
value += 1;
}
}
get 方法和 add 方法分别加了不同的所,所以源码为非线程安全。
注意事项
- 理清资源与锁的关系。
- 解决原子性问题,要保证中间状态对外不可见。
- 不能使用可变对象做锁。