Synchronized 是由Java SDK自带的轻量级的同步锁,可以非常方便的解决在多线程环境下的资源竞争问题,本篇主要讲述相关的用法以及注意点,以便能更好的使用同步锁。
使代码具有 原子性(atomicity)和 可见性(visibility),支持锁方法、锁对象、锁字符串
锁方法时,锁的是类的this变量,区分实例方法和静态方法的区别
锁对象时,锁的是对象的this变量
锁字符串时,锁的是字符串,这里要注意锁的是不是同一个字符串,如果是动态字符串它不是在String Pool中存储的,需要用intern().
特点
- 使用简单,无需手动释放锁
- 不支持条件对象
- 不能中断一个正在试图获得锁的线程
- 试图获得锁时不能设定超时等
先看一个反例,对余额进行1000次累加后,最后的输出结果可能是999
public class Bank {
private Double money = 0D;
public void add(Double money) {
this.money = this.money + money;
}
@Test
public void synchronizedMethod() throws InterruptedException {
private Bank bank = new Bank();
for (int i = 0; i < 1000; i++) {
new Thread(new Runnable() {
public void run() {
bank.add(1d);
}
}).start();
}
Thread.sleep(2000);
System.out.println(bank.getMoney());
}
...
}
为了解决这个问题,可以应用上面提到的三种方式
第一种 锁方法
public synchronized void add(Double money) {
this.money = this.money + money;
}
第二种 锁对象
public void add(Double money) {
synchronized (this) {
this.money = this.money + money;
}
}
第三种 锁字符串
public void add(Double money) {
synchronized ("Lock") {
this.money = this.money + money;
}
}
// 锁字符串,要特别注意,如果是new String()是存储在堆中的,而不是在常量池,需要用intern().
网友评论