线程的同步和锁
问题引出
为避免多线程对同一个对象进行操作,对数据造成的破坏。
问题解决
public class Tt extends Thread{
private Money money;
public Tt(Money money) {
this.money = money;
}
@Override
public void run() {
for (int i = 0; i < 3; i++) {
this.takeIt(30);
System.out.println(Thread.currentThread().getName()+"->"+money.getMoney());
}
}
public int takeIt(int x) {
return money.takeIt(x);
}
public static void main(String[] args) {
Money m = new Money();
Tt t1 = new Tt(m);
Tt t2 = new Tt(m);
t1.start();
t2.start();
}
}
- 确定资源对象为同一个对象
同步和锁定
- 非静态方法同步
- 只能同步方法,不能同步属性和类
- 只有拿到锁的线程才会执行方法,其余线程进入到阻塞状态
- 只针对同步方法,非同步方法不受锁的约束
- 如果持锁线程睡眠(sleep),其所持锁不会释放
- 线程可以获得多个锁,比如在一个同步方法中调用另一个同步方法,该线程同时持有二个对象的锁
- 线程同步埙害并发性,应尽量缩小同步的范围
- 使用同步代码块的时候,应确定在那个对象上同步,也就是获取那个对象的锁,效果等同于同步整个方法,但范围缩小了.
- 静态方法同步
- 用于整个类对象的锁,这个对象就是这个类(xx.class)
- 何时需要同步
当多个线程之间存在可交换的数据时,为保证该数据的唯一性及准确性,避免多个线程同时修改他而造成的资源破坏问题. - 未获得锁线程状态
会进入到阻塞状态,知道持有锁的线程释放,线程变为等待可运行或运行.
当考虑阻塞时,一定要注意那个对象正在被锁定
- 运行在同一个对象的非静态同步方法线程将会阻塞
- 运行在同一个类中静态同步方法的线程将会阻塞
- 运行在一个类中的静态同步方法和非静态方法永远不会阻塞
- 运行在不同对象的同一个同步方法将永远不会阻塞
- 线程安全类
- 没有绝对的安全
- 小结
- 线程的同步是为了防止多线程访问同一个资源是对资源的破坏
- 运行在非静态同步方法时获得的是对象锁
- 运行在静态同步方法时获得的时类对象锁
- 类对象锁和对象锁互不影响,一个线程可以获取多个锁
- 对于同步,时刻要明白是在那个对象之上的同步
- 多个线程争夺一个资源对象时,会造成线程阻塞的问题
- 死锁是多个线程相互等待造成的