心得3--由售票系统中的抢票机制解说同步线程及死锁案例分析

时间:2021-12-23 16:39:51

一.  这里跟大家分享一下售票系统,这里是一个抢票系统,讨论一下线程同步的作用(关键字synchronized),第一种是正确的程序,下面两种分别是两种不同的错误。

1.运用synchronized同步做的售票程序

packagecom.javaEE.code.synchronizedDemo;

classSellTicket{
public static int tickets = 10;
public synchronized void action(String name){
System.out.println(name+"抢到了"+tickets+"号票");
tickets--;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TicketThread extends Thread{
String name;
SellTicket t;
public TicketThread(SellTicket t, String name) {
this.t = t;
this.name = name;
start();
}
public void run() {
for(int i=0;i<5;i++){
t.action(name);
}
}
}
public class TestTicket{
public static void main(String[] args) {
SellTicket t = new SellTicket();
TicketThread t1 = new TicketThread(t,"小刚");
TicketThread t2 = new TicketThread(t,"洋洋");
}
}
2.sychronized的特殊情况(错误1)

packagecom.javaEE.code.synchronizedDemo;
/**
* 这种情况就是synchronized的特殊情况,同一个类的不同对象不能用这种方法上锁。
* */
public class Ticket extends Thread {
String name;
public static int tickets = 10;
public Ticket(String name, int tickets) {
super();
this.name = name;
Ticket.tickets = tickets;
}
//这里的锁方法是不管用的。
public synchronized void action(String name){
System.out.println(name+"抢到了"+tickets+"号票");
tickets--;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Ticket t1 = new Ticket("小刚",tickets);
Ticket t2 = new Ticket("洋洋",tickets);
t1.start();
t2.start();
}
public void run() {
for(int i=0;i<5;i++){
action(name);
}
}
}
3.不用同步做的存在安全隐患的售票系统(错误2)

packagecom.javaEE.code.synchronizedDemo;
/**
* 这种情况是一种错误的情况,两人同时抢票,可能第一个人强的票刚售出去(输出),总票数还没减去这张票,第二个人又来买票,这时就有可能买的是同一张票了。
* */
public class TicketError extends Thread {
String name;
public static int tickets = 10;
public TicketError(String name, int tickets) {
super();
this.name = name;
TicketError.tickets = tickets;
}
public static void main(String[] args) {
TicketError t1 = new TicketError("小刚",tickets);
TicketError t2 = new TicketError("洋洋",tickets);
t1.start();
t2.start();
}
public void run() {
for(int i=0;i<5;i++){
System.out.println(name+"抢到了"+tickets+"号票");
tickets--; //这里未减一第二个人就来抢票了
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

二.  死锁案例及分析

packagecom.javaEE.code.deadLock;

 

publicclass DeadLock implements Runnable{

   privatebooleanflag;

   public DeadLock(boolean flag) {

      this.flag = flag;

   }

   publicstaticvoid main(String[]args) {

      DeadLock dl1 = new DeadLock(true);

      DeadLock dl2 = new DeadLock(false);

      Thread t1 = new Thread(dl1);

      Thread t2 = new Thread(dl2);

      t1.start();

      t2.start();

   }

   @Override

   publicvoid run() {

      //if(){}else{}嵌套,模拟死锁

      if(flag){

        synchronized(MyLock.ml1){

           System.out.println(Thread.currentThread().getName()+"这是if语句的ml1");

           synchronized(MyLock.ml2){

              System.out.println(Thread.currentThread().getName()+"这是if语句的ml2");

           }

        }

      }else{

        synchronized(MyLock.ml2){

           System.out.println(Thread.currentThread().getName()+"这是else语句的ml2");

           synchronized(MyLock.ml1){

              System.out.println(Thread.currentThread().getName()+"这是else语句的ml1");

           }

        }

      }

     

   }

}

/**

 * 自定义锁,被同步代码块synchronized所调用

 * */

class MyLock{

      static MyLock ml1 = new MyLock();

      static MyLock ml2 = new MyLock();

}

输出结果为:Thread-0这是if语句的ml1

Thread-1这是else语句的ml2

   可见死锁现象已浮出水面,这里的两个线程都只运行了一步,下一步则被互相牵制,即互斥锁。