//目前只学了内置锁,即synchronize。只加了关键字就上了锁,并且解锁的过程不需要我们去管就可以了。还提供了Api,Lock接口实现;
    //Lock接口由几个方法;lock()获取锁,trylock()表示尝试获取锁,这种只有在锁空闲时才能获得;tryLock(),unLock()释放锁
    //可以直接读取Lock接口的源码方式实现;


    //可以发现Lock接口有两个实现类,一个时ReentrantLock类,叫做可重入锁类

可以使用Lock接口来替换掉synchronized关键字:

lock锁的获取,最终都会被是释放,所以使用finally关键字用于释放锁;这就是finally常用的作用;


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class WindowSellTickets implements Runnable{
    private static int count = 100;
    private static Lock lock = new ReentrantLock();
    String name;

    public WindowSellTickets(String name) {
        this.name = name;
    }

    @Override
    public void run() {

        while (count > 0 ){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            System.out.println(name + "卖票一张,剩余:" + count-- + "张!");//(什么都不加的情况下)

            //不加同步代码块的情况下,线程可能对一共享资源进行抢占,从而导致线程争抢的问题;下面是解决此问题的方法


            //  synchronized(WindowSellTickets.class) {
            //  System.out.println(name + "卖票一张,剩余:" + count-- + "张!");
            //  }

            //可以使用Lock接口的实现类的方式以及所能提供的方法来实现对对象加锁,替换掉synchronized关键字

            lock.lock();//lock.lock()给对象上了锁
            try {
                System.out.println(name + "卖票一张,剩余:" + count-- + "张!");
            } finally {
                lock.unlock();//使用finally关键字保障锁一定会被释放掉
            }
            
            
        }

    }

    public static void main(String[] args) {
        Thread t1 = new Thread(new WindowSellTickets("窗口1"));
        Thread t2 = new Thread(new WindowSellTickets("窗口2"));
        t1.start();
        t2.start();

    }
}