一、Synchronized锁
-
线程就是一个单独的资源类,没有任何的附属操作!(拿来即用)
-
企业开发中,尽量避免下面线程创建方式,这种方式耦合度高
-
推荐使用下面方式创建线程,解耦!
/** * @author swaggyhang * @create 2023-07-01 10:49 */ public class Test01 { public static void main(String[] args) { // 并发:多个线程操作同一个资源类,把资源类丢入线程中 Ticket ticket = new Ticket(); // Runnable有@FunctionalInterface注解,是一个函数式接口,可以使用lambda表达式 new Thread(() -> { // 循环60次去卖票,肯定能卖完50张票 for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "A").start(); new Thread(() -> { for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "B").start(); new Thread(() -> { for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "C").start(); } } // 资源类 class Ticket { // 50张票 private int number = 50; // 卖票 public synchronized void sale() { if (number > 0) { System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "票,还剩余" + number + "张票"); } } }
二、Lock锁
-
Lock接口的三个常用实现类
-
基本使用
-
ReentrantLock的无参构造器,默认构造的是非公平锁
-
公平锁和非公平锁
① 公平锁:十分公平,保证线程先来后到
② 非公平锁:十分不公平,线程可以插队(Synchronized锁和Lock锁默认都是非公平锁) -
代码演示
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @author swaggyhang * @create 2023-07-01 11:45 */ public class Test02 { public static void main(String[] args) { // 并发:多个线程操作同一个资源类,把资源类丢入线程中 Ticket02 ticket = new Ticket02(); // Runnable有@FunctionalInterface注解,是一个函数式接口,可以使用lambda表达式 new Thread(() -> { // 循环60次去卖票,肯定能卖完50张票 for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "A").start(); new Thread(() -> { for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "B").start(); new Thread(() -> { for (int i = 1; i <= 60; i++) { ticket.sale(); } }, "C").start(); } } // 资源类 class Ticket02 { // 50张票 private int number = 50; private Lock lock = new ReentrantLock(); // 卖票 public void sale() { // 加锁 lock.lock(); try { // 业务代码 if (number > 0) { System.out.println(Thread.currentThread().getName() + "卖出了第" + (number--) + "票,还剩余" + number + "张票"); } } catch (Exception e) { e.printStackTrace(); } finally { // 解锁 lock.unlock(); } } }
三、Synchronized锁和Lock锁区别
- Synchronized是内置的Java关键字,Lock是一个Java接口
- Synchronized无法判断是否获取到了锁,Lock可以判断是否获取到了锁
- Synchronized会自动释放锁(线程执行完或者线程抛出异常都会释放锁),Lock必须要手动释放锁(如果不手动释放锁,会造成死锁)
- Synchronized如果线程1获得锁(阻塞了),线程2就处于等待(死死的等);Lock就不一定会等待下去(lock.tryLock()方法尝试获取锁)
- Synchronized是可重入锁,不可以中断的,且是非公平锁;Lock是可重入锁,但可以中断,默认非公平锁(可以设置为公平锁)
- Synchronized适合锁少量的代码同步问题,Lock适合锁大量的同步代码