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