LockExercise
package LockExercise20240812;
public class LockExercise {
public static void main(String[] args) {
// Synchronized同步代码块或同步方法通过锁对象解决了数据安全的问题,但是并没有清晰的看见在何处上锁和解锁,
// 所以说在JDK5之后提供了一个新的锁对象Lock,可以清晰地表达如何上锁和解锁
// Lock是一个接口,不能直接实例化,可以通过其实现类ReentrantLock进行实例化
// ReentrantLock() 创建一个ReentrantLock对象
// void lock() 上锁
// void unlock() 解锁
SellTickets st = new SellTickets();
Thread thread1 = new Thread(st, "窗口1");
Thread thread2 = new Thread(st, "窗口2");
Thread thread3 = new Thread(st, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
SellTickets
package LockExercise20240812;
import java.util.concurrent.locks.ReentrantLock;
public class SellTickets implements Runnable {
private static int tickets = 100;
private static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();
try {
if (tickets <= 0) {
break;
} else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
tickets--;
System.out.println(Thread.currentThread().getName() + ": 正在卖第" + (100 - tickets) + "张票");
}
} finally {
lock.unlock();
}
}
}
}
//package LockExercise20240812;
//
//import java.util.concurrent.locks.ReentrantLock;
//
//public class SellTickets implements Runnable {
// private static int tickets = 100;
// private static ReentrantLock lock = new ReentrantLock();
//
// @Override
// public void run() {
// while (true) {
// lock.lock();
// if (tickets <= 0) {
// return;
// } else {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// tickets--;
// System.out.println(Thread.currentThread().getName() + ": 正在卖第" + (100 - tickets) + "张票");
// }
// lock.unlock();
// }
// }
//}
// 将unlock方法写在了if - else之外,假如tickets的值小于等于0,线程会直接返回而不会释放锁,
// 这可能导致其他线程无法获取锁(因为其他线程已经进入循环了,在等待那把锁,假如一直没有就会陷入死锁状态)从而进入死锁状态