一、synchronized代码块实现售票
1、首先synchronized就像一把锁,多个线程同时竞争synchronized代码块的资源,当一个线程先抢到这个资源时,就会上锁,别的线程就不能访问,只能等到当前线程执行完sychronized里面的代码才会释放锁,然后别的线程才可以竞争访问,接着又是上锁和释放锁的过程。
2、synchronized实现简单售票代码:
import java.util.concurrent.TimeUnit;
/**
* synchronized代码块实现简单售票
*
* @author limingxing
*
*/
public class SaleTest {
public static void main(String[] args) {
SaleTicket st = new SaleTicket();
//三个线程同时售票
new Thread(st).start();
new Thread(st).start();
new Thread(st).start();
}
}
class SaleTicket implements Runnable {
private int ticket = 20;//假设有20张票
@Override
public void run() {
while (true) {
synchronized (this) {
try {
//使当前线程休眠1秒,休眠期间不会释放锁,其它线程不能访问。
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket == 1) {
--ticket;
System.out.println(Thread.currentThread().getName() + ":售一张,票售完了");
break;
} else if(ticket == 0){
System.out.println(Thread.currentThread().getName() + ":票售完了");
break;
}else {
System.out.println(Thread.currentThread().getName() + ":售一张,票还剩:" + (--ticket) + "张");
}
}
}
}
}
3、结果
4、上面有三个线程去售票,假设为A、B、C三个线程,假设此时都到Run方法中while(true)里面了,这时候A先得到锁,然后B、C都被阻挡在锁的外面,一直等待锁的释放,当A执行完所里面的代码,就会释放锁;三个线程又同时竞争锁,再释放锁,就一直循环下去,一直到票售完了,跳出循环,结束售票。
二、synchronized修饰方法实现简单售票
1、原理和代码块差不多,用synchronized关键字修饰方法,将方法的内容锁起来,方法里面的内容每次只能让一个线程访问。
2、代码
import java.util.concurrent.TimeUnit;
/**
* synchronized方法
* @author limingxing
*
*/
public class SaleTest2 {
public static void main(String[] args) {
TicketTest tt = new TicketTest();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class TicketTest implements Runnable{
private int ticket = 20;
@Override
public void run() {
while(true) {
if(!sale()) {
break;
}
}
}
public synchronized boolean sale() {
try {
//使当前线程休眠1秒,休眠期间不会释放锁,其它线程不能访问。
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ticket == 1) {
--ticket;
System.out.println(Thread.currentThread().getName() + ":售一张,票售完了");
return false;
} else if(ticket == 0){
System.out.println(Thread.currentThread().getName() + ":票售完了");
return false;
}else {
System.out.println(Thread.currentThread().getName() + ":售一张,票还剩:" + (--ticket) + "张");
return true;
}
}
}
3、结果