1、使用synchronized
public class SaleTicketDemo {
public static void main(String[] args) {
// 多个售票员售票
Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}, "A").start();
new Thread(() -> {
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 Ticket {
// 拥有30张票
private int num = 30;
// 使用synchronized同步执行卖票操作
public synchronized void sale() {
if (num > 0) {
// 卖票
System.out.println(Thread.currentThread().getName() + ": " + --num);
}
}
}
2、使用Lock
public class SaleTicketWithLock {
public static void main(String[] args) {
Ticket2 ticket2 = new Ticket2();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
ticket2.sale();
}
}, "C").start();
}
}
class Ticket2 {
private int num = 30;
Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try {
if (num > 0) {
System.out.println(Thread.currentThread().getName() + ": " + --num);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
总结
1、synchronized 内置的Java关键字,Lock 是一个Java接口
2、synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
3、synchronized 会自动释放锁,Lock必须要手动释放锁!如果不释放锁,死锁
4、synchronized 线程1(获得锁,阻塞)、线程2(等待);Lock锁可以使用lock.lockInterruptibly(),如果没获取到锁,也可以继续执行下面的逻辑;
5、synchronized 可重入锁,不可以中断的,非公平;Lock,可重入锁,可以判断锁,非公平(可以自己设置)
6、synchronized 适合锁少量的代码同步问题,Lock适合锁大量的代码同步