1.线程并发的产生
这里举一个买票的经典案例:四个窗口售卖100涨车票,代码如下:
public class Ticket implements Runnable{ /**线程名称*/ private String name; /**车票库存*/ static int tickets = 100; /**构造器*/ public Ticket(String name){ this.name = name; } @Override public void run(){ while (true){ if(tickets>0){ System.out.println(name+"窗口正在售卖第"+(tickets--)+"张票"); }else { break; } } System.out.println(name+"窗口售完票"); } }
运行后发现存在多个窗口成功售卖同一张票,这样不符合实际需求的情况就是线程的并发。
2.线程并发的解决
使用synchronized关键字,语法如下:
synchronized(锁对象){ //操作共享资源的代码 }
同步代码加在什么地方?
(1)代码被多个线程访问;
(2)代码中有共享的数据;
(3)共享数据被多条语句操作;
修改买票案例,代码如下:
public class Ticket implements Runnable{ /**车票库存*/ int tickets = 100; /**创建一个锁对象,这个对象有多个线程共同使用*/ static Object obj = new Object(); @Override public void run(){ while (true){ //多线程共享代码块 synchronized (obj) { if (tickets > 0) { System.out.println(Thread.currentThread().getName() + "窗口正在售卖第" + (tickets--) + "票"); } else { break; } } } System.out.println(Thread.currentThread().getName()+"窗口售完票"); } public static void main(String args[]){ Ticket ticket = new Ticket(); Thread thread1 = new Thread(ticket,"窗口1"); Thread thread2 = new Thread(ticket,"窗口2"); Thread thread3 = new Thread(ticket,"窗口3"); Thread thread4 = new Thread(ticket,"窗口4"); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } }
*注意:本次改造把整个Ticket类作为了共享对象