1.定义
Java中的Lock锁是一种线程同步机制,它可以让多个线程在并发执行时保持互斥访问某个共享资源,以避免数据不一致或竞态条件等问题。与传统的synchronized关键字相比,Lock提供了更灵活和强大的功能,例如可重入性、公平性、超时等待以及条件变量等,同时也可以避免死锁问题。
2.优点
①Lock锁提供了更加灵活的锁定机制,可以实现更复杂的线程同步需求,比如公平锁、可重入锁、读写锁等。而synchronized锁只能实现基本的互斥锁。
②Lock锁需要手动获取和释放锁,因此需要开发者自行控制锁的获取和释放顺序。而synchronized锁的获取和释放都由JVM自动完成,在方法执行结束或抛出异常时会自动释放锁。
3.如何使用
①创建一个Lock对象,通常使用ReentrantLock类实现。
②在需要进行同步的代码块前调用Lock对象的lock()方法获取锁。
③执行同步代码块。
④最后一定要调用Lock对象的unlock()方法释放锁,以便其他线程可以获取锁并执行同步代码。
例如:
- 创建一个Lock对象,通常使用ReentrantLock类实现。
- 在需要进行同步的代码块前调用Lock对象的lock()方法获取锁。
- 执行同步代码块。
- 最后一定要调用Lock对象的unlock()方法释放锁,以便其他线程可以获取锁并执行同步代码。
例如:需求:
请使用多线程解决三个买票窗口共同卖500张票的问题
package Multithreading.Lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; //使用Lock锁步骤:1.创建一个Lock对象,通常使用ReentrantLock类实现。 //2.在需要进行同步的代码块前调用Lock对象的lock()方法获取锁。 //3.执行同步代码块。 //4.最后一定要调用Lock对象的unlock()方法释放锁, // 以便其他线程可以获取锁并执行同步代码. //题目:请使用多线程解决三个买票窗口共同卖500张票的问题 public class MyThread extends Thread { //因为需求所需锁唯一,所以用static修饰 //实例化Lock锁,创建对象 static Lock lock = new ReentrantLock(); //票为共享的所以要static修饰 static int tickets=0; //继承Thread类覆盖run方法 public void run() { while(true){ //上锁 lock.lock(); //同步代码块 try { //让线程睡眠10毫秒 Thread.sleep(10); if(tickets<500){ tickets++; System.out.println(getName()+"正在卖第"+tickets+"张票"); }else { break; } } catch (InterruptedException e) { e.printStackTrace(); }finally { //开锁 lock.unlock(); } } } }
package Multithreading.Lock; public class Test { public static void main(String[] args) { MyRunnable mc = new MyRunnable(); Thread t1 = new Thread(mc,"窗口1"); Thread t2 = new Thread(mc,"窗口2"); Thread t3 = new Thread(mc,"窗口3"); t1.start(); t2.start(); t3.start(); } }