解决java多线程中线程安全的三种方式
1.什么是线程安全
private int count = 100;
@Override
public void run() {
while(true){
if(count>0){
System.out.println(Thread.currentThread().getName()+"卖出第"+count+"张票");
count--;
}
}
}
上述代码中,假设3个线程ABC同时访问count变量,假设A在打印后失去了CPU的拥有权,此时count并未–,这时B拥有了cpu而此时count是100,这就造成了,他们同时卖出了第100张票,此时线程不安全
解决方式1利用同步锁(同步代码块)
while(true){
synchronized (obj){
if(count>0){
System.out.println(Thread.currentThread().getName()+"卖出第"+count+"张票");
count--;
}
}
}
利用synchronized (锁对象){}格式将线程不安全代码包裹,这时当线程到达时会先获取锁对象,执行完会释放锁对象,在运行过程中其他线程到达时拿不到锁对象,并不能执行代码,注意锁对象可以是任意对象
解决方式2利用同步方法
public void run() {
while(true) {
this.sale();
}
}
private synchronized void sale(){
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "卖出第" + count + "张票");
count--;
}
}
同步方法是利用在方法声明时加上synchronized 关键字即可,内部也是利用锁对象来确定访问权限的,而这里的锁对象是this,注意:若方法是静态的则锁对象是该类的字节码
解决方式3利用Lock方式(推荐*)
lock是一个接口,主要是使用它的实现类
创建类ReentrantLock在不安全代码块之前上锁,在代码结束时释放锁,这种做法的好处,可以在try前上锁,在finally解锁,出现异常亦可以很方便的解锁
private int count = 1000;
Lock lock = new ReentrantLock();
@Override
public void run() {
while(true) {
lock.lock();
if (count > 0) {
System.out.println(Thread.currentThread().getName() + "卖出第" + count + "张票");
count--;
}
lock.unlock();
}
}