一言不合就贴出代码:
以下就是三个线程同时操作一个对象:
public class MyThread2 extends Thread {
private Personal personal;
public MyThread2(Personal personal){
this.personal = personal;
}
@Override
public void run() {
System.out.println(this.getName()+":"+personal.getName());
System.out.println(this.getName()+":"+personal.getAge());
System.out.println(this.getName()+":"+personal.getSex());
}
}
public static void main(String[] args){
Personal personal = new Personal();
personal.setName("zangsan");
personal.setAge(11);
personal.setSex((byte) 1);
MyThread2 t1 = new MyThread2(personal);
MyThread2 t2 = new MyThread2(personal);
MyThread2 t3 = new MyThread2(personal);
t1.start();
t2.start();
t3.start();
}
运行结果:
Thread-2:zangsan
Thread-0:zangsan
Thread-1:zangsan
Thread-0:11
Thread-2:11
Thread-0:1
Thread-1:11
Thread-2:1
Thread-1:1
从运行结果,感觉还行,没什么问题,但是,真的是这样吗?
public class ThreadLocalDemo {
public static void main(String[] args){
Buys buys = new Buys();
//初始化总现金
buys.setTotal(100);
MyThread2 t1 = new MyThread2(buys);
MyThread2 t2 = new MyThread2(buys);
MyThread2 t3 = new MyThread2(buys);
t1.start();
t2.start();
t3.start();
}
}
public class MyThread2 extends Thread {
private Buys buys;
public MyThread2(Buys buys){
this.buys = buys;
}
@Override
public void run() {
//执行买香烟的业务,一包烟20块钱
buys.setTotal(buys.getTotal() - 20);
System.out.println(this.getName()+":剩余现金有"+buys.getTotal());
}
}
运行结果:
Thread-1:剩余现金有80
Thread-2:剩余现金有60
Thread-0:剩余现金有80
从这个运行结果来看,显然存在很大的问题,三个人(三个线程)用这个100块钱都做一个买烟的业务,剩余的现金应该都是80,60,40才对吧。
这就是所谓的线程不安全。
解决办法是在关键业务上给Buys对象加锁
//执行买香烟的业务,一包烟20块钱
synchronized (buys){
buys.setTotal(buys.getTotal() - 20);
System.out.println(this.getName()+":剩余现金有"+buys.getTotal());
}
运行结果是:
Thread-1:剩余现金有80
Thread-2:剩余现金有60
Thread-0:剩余现金有40
好了, 线程安全了。
总结:
(1)Synchronized给对象加锁,使同一时间只能有一个线程操作对象;
(2)只有一个线程执行结束另一个线程才能继续执行业务;
(3)线程虽然安全了,但是并行操作变成了并发操作,速度相对变慢了,在资源竞争比较激烈的情况下,显然Synchronized执行效率很慢(要理解串行、并行、并发的概念)
那么能不能做到既安全又快速的办法呢?这里有介绍Java并发编程:Lock
场景:
当资源竞争比较激烈时,用Lock;反之,用Synchronized。