解决线程安全问题——Lock锁
解决线程安全问题的三种方案:使用Lock锁java.util.concurrent.locks.Lock
接口
Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
Lock接口中的方法:
**void lock()**获取锁。
**void unlock()**释放锁。
java.util.concurrent.locks.ReentrantLock implements Lock接口
使用步骤:
1.在成员位置创建一个ReentrantLock对象
2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
public classRunnableImpl implements Runnable{
//定义一个多个线程共享的票源
private int ticket = 100; //1.在成员位置创建一个ReentrantLock对象 Lock l = new ReentrantLock(); //设置线程任务:卖票 @Override public void run() { //使用死循环,让卖票操作重复执行 while(true){ //2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁 l.lock(); //先判断票是否存在 if(ticket>0){ //提高安全问题出现的概率,让程序睡眠 try { Thread.sleep(10); //票存在,卖票 ticket-- System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票"); ticket--; } catch (InterruptedException e) { e.printStackTrace(); }finally { //3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁 l.unlock();//无论程序是否异常,都会把锁释放 } } } } /*//设置线程任务:卖票 @Override public void run() { //使用死循环,让卖票操作重复执行 while(true){ //2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁 l.lock(); //先判断票是否存在 if(ticket>0){ //提高安全问题出现的概率,让程序睡眠 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //票存在,卖票 ticket-- System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票"); ticket--; } //3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁 l.unlock(); } }*/ }
package com.itheima.demo09.Lock;
/* 模拟卖票案例 创建3个线程,同时开启,对共享的票进行出售 */ public class Demo01Ticket { public static void main(String[] args) { //创建Runnable接口的实现类对象 RunnableImpl run = new RunnableImpl(); //创建Thread类对象,构造方法中传递Runnable接口的实现类对象 Thread t0 = new Thread(run); Thread t1 = new Thread(run); Thread t2 = new Thread(run); //调用start方法开启多线程 t0.start(); t1.start(); t2.start(); } }