卖票例子,用synchronized关键字实现。
package juc.sync;
class Ticket{
//票数
private int number = 30;
public synchronized void sale(){
if(number > 0) {
System.out.println(Thread.currentThread().getName() + ": 卖出" + (number--) + ", 还剩:" + number );
}
}
}
public class SaleTicket {
public static void main(String[] args) {
//创建Ticket 对象
Ticket ticket = new Ticket();
//创建三个线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
},"售票员AA").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
},"售票员BB").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
},"售票员CC").start();
}
}
用Lock 可重入锁实现卖票
import java.util.concurrent.locks.ReentrantLock;
class LTicket{
//票数
private int number = 30;
//创建可重入锁
private final ReentrantLock lock = new ReentrantLock();
//卖票方法
public void sale(){
//首先上锁
lock.lock();
try {
if(number > 0) {
System.out.println(Thread.currentThread().getName() + ": 卖出" + (number--) + ", 还剩:" + number );
}
}finally {
//解锁
lock.unlock();
}
}
}
public class LSaleTicket {
public static void main(String[] args) {
LTicket ticket = new LTicket();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"售票员AA").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"售票员BB").start();
new Thread(()->{
for (int i = 0; i < 40; i++) {
ticket.sale();
}
},"售票员CC").start();
}
}
Lock和synchroized 的不同
- Lock是一个接口,而synchroized是Java中的关键字,有内置语言实现synchroized在发生异常时,会自动释放线程占用的锁,不会导致死锁的发生。而Lock发生异常时,如果没有主动释放锁,很可能会造成死锁Lock 可以让等待锁的线程响应中断,而synchroized不行,使用synchroized时,等待线程会一直等待下去,不能响应中断。通过Lock可以知道有没有成功获取锁,而synchroized不能办到Lock可以提高多线程进行读的效率,大量线程同时竞争Lock性能远远优于synchroized



