Java多线程(二)线程安全问题
什么是线程安全问题?
多个线程操作同一个共享资源的时候可能会出现线程安全问题。
如何解决线程安全问题?
使用线程同步
线程同步
什么是线程同步?
线程同步是多个线程同时访问同一个资源。
线程同步的作用:
就是为了解决线程安全问题的方案
如何实现线程同步?
把共享资源进行上锁,每次只能一个线程进入访问完毕后,其他线程才能继续访问。
线程同步的方式有三种:
--1.同步代码块
--2.同步方法
--3.lock显示锁 同步代码块
同步代码块
作用:把出现线程安全问题的核心代码给上锁,每次只能一个线程进入,执行完毕以后自动上锁,其他线程才可以进来执行。
格式:
synchronized(锁对象){
//访问共享资源的核心代码
}
锁对象建议使用共享资源
--在实例方法中建议使用this作为锁对象。此时this正好是共享资源!
--在静态方法中建议使用类名.class字节码作为锁对象。
synchronized (this){
if(this.money >= money){
System.out.println(name+"来取钱,吐出:"+money);
this.money -= money;
System.out.println(name+"来取钱"+money+"成功,取钱后剩余:"+this.money;
}else{
System.out.println(name+"来取钱,余额不足,剩余"+this.money;
}
}
//张三来取钱,吐出:10000
//张三取钱成功,取钱后剩余0
//李四来取钱,余额不足,剩余0
同步方法
作用:
把出现线程安全问题的核心方法给锁起来
每次只能使一个线程进入访问,其他线程必须在方法外面等待。
用法:
直接给方法加上一个修饰符 synchronized
public synchronized void ThreadDemo(){
if(this.money >= money){
System.out.println(name+"来取钱,吐出:"+money);
this.money -= money;
System.out.println(name+"来取钱"+money+"成功,取钱后剩余:"+this.money;
}else{
System.out.println(name+"来取钱,余额不足,剩余"+this.money;
}
}
lock显示锁
java.util.concurrent.locks.Lock机制提供了比synchronized代码块和synchronized方法更广泛的锁操作,同步代码块/同步方法具有的功能Lock锁都有,除此之外更强大更方便
Lcok锁也称同步锁,加锁与释放锁方法化了,如下:
--public void lock() //:加同步锁
--public void unlock() //:释放同步锁
实例:
//创建一把锁
private final Lock lock = new ReentrantLock();
lock.lock(); //上锁
try{
if(this.money >= money){
System.out.println(name+"来取钱,吐出:"+money);
this.money -= money;
System.out.println(name+"来取钱"+money+"成功,取钱后剩余:"+this.money;
}else{
System.out.println(name+"来取钱,余额不足,剩余"+this.money;
}catch (Exception e){
e.printStackTrace();
}finally{
lock.unlock(); //解锁
}
}