其他分享
首页 > 其他分享> > 静态同步方法以及Lock锁

静态同步方法以及Lock锁

作者:互联网

静态同步方法

class RunnaleImpl implements Runnable{
    //定义一个多个线程共享的票源
    private static int ticket = 100;
    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环让卖票操作重复执行
        while (true){
            payTicket();
        }
    }
    //定义一个同步方法
    public static synchronized void payTicket(){
        //判断票是否存在
        if (ticket>0){
            //提高安全问题出现的概率,让程序睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //票存在,卖票,ticket--
            System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
            ticket--;
        }
    }
}
public class Demo01Ticket {
    /**
     * 模拟卖票案例
     * 创建3个线程,同时开启,对共享的票进行出售
     */
    public static void main(String[] args) {
        RunnaleImpl ru = new RunnaleImpl();
        Thread t0 = new Thread(ru);
        Thread t1 = new Thread(ru);
        Thread t2 = new Thread(ru);
        t0.start();
        t1.start();
        t2.start();
    }
}

静态同步方法的锁对象不能是this。

this是创建对象之后产生的,静态方法优先于对象

静态方法的锁对象是本类的class属性——>class文件对象

    //定义一个同步方法
    public static /*synchronized*/ void payTicket(){
        synchronized (RunnaleImpl.class){
            //判断票是否存在
            if (ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //票存在,卖票,ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }
    }
}

 

 

 

 

 

解决线程安全问题—Lock锁

一、Lock锁

  虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

  Lock实现提供比使用synchronized方法和语句更广泛的锁定操作

二、Lock中提供了获得锁和释放锁的方法

  1.void lock():获得锁

  2.void unlock();释放锁

  Lock由于是接口,不能直接实例化,这里采用它的实现类ReentrantLock来实例化

三、ReentrantLock的构造方法

  ReentrantLock():创建一个ReentrantLock的实例

使用步骤:
  1.在成员位置创建一个ReentrantLock对象

  2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁

  3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁

class RunnaleImpl implements Runnable{
    //定义一个多个线程共享的票源
    private static 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);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //票存在,卖票,ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }

            //3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁
            l.unlock();
        }
    }
}

添加Lock锁之后,程序照样不会出现重票的和不存在票的现象

 @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();
                }
            }
        }
    }

同样也可以将unlock写在finally代码块中,这样不管程序会不会出现异常都会释放锁,可以提高程序的效率

 

标签:同步,卖票,Thread,静态,Lock,void,--,ticket
来源: https://www.cnblogs.com/xjw12345/p/16460735.html