Lock接口

52 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

2.1、Synchronized

是一种同步锁,修饰的对象有以下几种:

1、修饰一个代码块,被修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象。

2、修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象。

synchronized并不属于方法定义的一部分。因此,synchronized关键字不能被继承。

synchronized卖票小实例

 /**
  * @author rop
  * @since 2022/10/9 21:34
  */
 public class SaleTicket {
     public static void main(String[] args) {
         // 第二步:创建多个线程,调用资源类的操作方法
         Ticket ticket = new Ticket();
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for (int i = 0; i < 40; i++) {
                     ticket.sale();
                 }
             }
         }, "A").start();
 ​
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for (int i = 0; i < 40; i++) {
                     ticket.sale();
                 }
             }
         }, "B").start();
 ​
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for (int i = 0; i < 40; i++) {
                     ticket.sale();
                 }
             }
         }, "C").start();
     }
 }
 ​
 // 第一步:创建资源类,定义属性和操作方法
 class Ticket {
     // 票数
     private int number = 30;
 ​
     // 操作方法:卖票
     // public void sale() {
     public synchronized void sale() {
         // 判断
         if (number > 0) {
             System.out.println(Thread.currentThread().getName()
                     + "卖出了第 " + ( number-- ) + " 张票,还剩:" + number + "张");
         }
     }
 }

2.2、什么是Lock接口

Lock锁实现提供了比使用同步方法和语句可以获得的更广泛的锁操作。它们允许更灵活的结构,可能具有非常不同的属性,并且可能支持多个关联的条件对象。Lock提供了比synchronized更多的功能。

Lock和Synchronized的区别

  • Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;
  • Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

2.3、Lock实现可重入锁

 private final ReentrantLock lock = new ReentrantLock();

再用这把锁上锁和解锁对应的操作

2.4、创建多线程的多种方式

  • Thread
  • Runnable
  • Callable

2.5、使用Lock实现卖票

 /**
  * @author rop
  * @since 2022/10/9 23:04
  */
 public class LTicketSale {
     public static void main(String[] args) {
         // 第二步:创建多个线程,调用资源类的操作方法
         LTicket ticket = new LTicket();
 ​
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for (int i = 0; i < 40; i++) {
                     ticket.sale();
                 }
             }
         }, "A").start();
 ​
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for (int i = 0; i < 40; i++) {
                     ticket.sale();
                 }
             }
         }, "B").start();
 ​
         new Thread(() -> {
             for (int i = 0; i < 40; i++) {
                 ticket.sale();
             }
         }, "C").start();
     }
 }
 ​
 // 第一步:创建资源类,定义属性和操作方法
 class LTicket {
     // 票数量
     private int number = 30;
     // 创建可重入锁
     private final ReentrantLock lock = new ReentrantLock();
 ​
     // 卖票
     public void sale() {
         // 上锁
         lock.lock();
 ​
         try {
             if (number > 0) {
                 System.out.println(Thread.currentThread().getName() + "卖了第" + ( number-- ) + "张票,还剩" + number + "张");
             }
         } finally {
             // 解锁
             lock.unlock();
         }
     }
 }