/**
* 创建三个窗口卖票,总票数100张,实现Runnnable接口的方式
*
* 1、问题:买票过程中,出现了错票重票-->出现了线程安全的问题
* 2、问题出现得原因:当某个线程操作钞票的过程红,尚未完成操作时,其他线程参与进来,也操作钞 票
* 3、如何解决:当一个线程a在操作ticket的时候,其他线程不能参与进来。直到线程a操作完成ticket 时,线程才可以开始操作ticket。
* 这种情况下即使a出现了阻塞,也不能被改变
* 4、在Java中,我们通过同步机制,来解决线程安全问题
* 方式一:同步代码块
* synchronized(同步监视器){
* //需要被同步的代码
* }
*
* 说明:1、操作共享数据的代码,即为需要被同步的代码
* 2、共享数据:多个线程操作的变量。比如ticket就是共享数据。
* 3、同步监视器,俗称:锁。任何一个类的对象,都可以充当锁
* 要求:多个线程必须要共用一把锁
*/
class Window1 implements Runnable {
private int ticket = 10000;
Object object=new Object();
@Override
public void run() {
while (true) {
synchronized(object){
if (ticket > 0) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "票");
ticket--;
} else {
break;
}
}
}
}
}
public class Window1Test {
public static void main(String[] args) {
Window1 window1=new Window1();
Thread t1=new Thread(window1);
Thread t2=new Thread(window1);
Thread t3=new Thread(window1);
t1.setName("线程一");
t2.setName("线程二");
t3.setName("线程三");
t1.start();
t2.start();
t3.start();
}
}
* 方式二:同步方法
/** * 使用同步方法处理继承Thread类中线程安全问题 * * 同步方法的总结: * 1、同步方法仍然涉及到同步监视器,只是我们不需要显式的声明 * 2、非静态的同步方法,同步监视器是this * 静态的同步方法,同步监视器是:当前类本身 */
class Window3 extends Thread{ private static int ticket=100; @Override public void run() { while (true){ show(); } } public static synchronized void show(){ if (ticket>0){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票"); ticket--; } } } public class WindowTest3 { public static void main(String[] args) { Window3 w1 = new Window3(); Window3 w2 = new Window3(); Window3 w3 = new Window3(); w1.setName("窗口1:"); w2.setName("窗口2:"); w3.setName("窗口3:"); w1.start(); w2.start(); w3.start(); } }
方式三:Lock
* 解决线程安全问题的方式三:Lock锁---JDK5.0新增 * 1、面试题:synchronized 与 lock的异同? * 相同:二者都可以解决线程安全的问题 * 不同:synchronized机制在执行完相应的同步代码以后,自动释放同步监视器 * lock需要手动的启动同步(lock()),同时结束同步时也需要手动的实现(nuclock())。 * 2、优先使用顺序 * lock->同步代码块(已经进入了方法体,分配了相应资源)->同步方法(在方法体外) * * 面试题:如何解决线程安全问题?有几种方式 * 三种:lock、同步代码块、同步方法