一. 这里跟大家分享一下售票系统,这里是一个抢票系统,讨论一下线程同步的作用(关键字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
可见死锁现象已浮出水面,这里的两个线程都只运行了一步,下一步则被互相牵制,即互斥锁。