package com.bupt.exer;
/**
* 列子:创建三个窗口卖票,总票数为100张,使用实现的runnable接口方式
* 1. 问题:买票过程中出现重票和错票
* 2.原因:当某个线程操作过程中,另一个线程也参与进来
* 3.解决方式:当一个线程a在操作ticket的时候,其他线程不能参与进来,
* 直到线程a操作完ticket时,其他线程才可以开始操作ticket,这种情况即使线程a
* 出现了阻塞,也不能被改变。
*
* 4. 在java中,我们通过同步机制,来解决线程安全问题
* 方式一: 同步代码块
* synchroized(同步监视器){
* //需要被同步的代码
* }
*说明:1、操作共享数据的代码,即为需要被同步的代码
* 2、共享数据:多个线程共同操作的代码,比如ticket
* 3、同步监视器,俗称锁,任何一个类的对象都可以称为锁。
* 要求:多个线程必须共用同一把锁
* 4、在继承Thread类中创建多线程方式中,慎用this充当同步显示器
* 可以考虑当前类来充当同步监视器
* 5、在实现Runnable接口创建多线程的方式中,我们可以考虑使用
* this充当同步监视器
* 方法二:同步方法
* 如果操作共享数据的代码完整声明在一个方法中,我们不妨将此方法声明为同步的
*
*5. 同步的方式解决了线程的安全问题----好处
* 操作同步代码时,只能有一个线程参与,其他线程等待,相当于一个单线程,效率低----局限性
*
*
*
*/
//使用同步方法解决Runnable接口的线程安全问题
class ticketWindows3 implements Runnable{
private int ticket = 100;
@Override
public void run() {
while (true) {
show();
if(ticket <= 0)
break;
}
}
public synchronized void show(){ //同步监视器默认为this
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ": " + ticket);
ticket--;
}
}
}
public class windows3 {
public static void main(String[] args) {
ticketWindows3 ticketWindows = new ticketWindows3();
Thread t1 = new Thread(ticketWindows);
Thread t2 = new Thread(ticketWindows);
Thread t3 = new Thread(ticketWindows);
t1.setName("a");
t2.setName("b");
t3.setName("c");
t1.start();
t2.start();
t3.start();
}
}
package com.bupt.exer;
//使用同步方法解决继承Thread的方式来卖票
/**关于同步方法总结
*1. 同步方法仍然涉及到同步监视器,只是不需要我们显示的声明
*2. 非静态的同步方法,同步监视器是,this
* 静态的同步方法,同步监视器是,当前类本身
*
*/
class ticketWindows4 extends Thread{
private static int ticket = 100;
private static Object obj = new Object();
@Override
public void run() {
while (true) {
show();
if(ticket <= 0)
break;
}
}
public static synchronized void show(){//同步监视器 ticketWindows4.class
// public synchronized void show(){ // 同步监视器t1,t2,t3此种方法并不安全,解决方式时错误的
if (ticket > 0) {
System.out.println(Thread.currentThread().getName() + ": " + ticket);
ticket--;
}
}
}
public class windows4 {
public static void main(String[] args) {
Thread t1 = new ticketWindows4();
t1.setName("t1");
Thread t2 = new ticketWindows4();
t2.setName("t2");
Thread t3 = new ticketWindows4();
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}