synchronize实现秒杀

项目中,我们经常会遇到一些秒杀情况:例如:我们就只有一定量的票数量;这个时候有多个窗口进行售卖;

这个时候其实就是多个线程对一个变量进行操作;这样很容易出现,当第一个线程在对全局变量进行操作时,另外一个进程也进来对变量进行操作;这样有一些时间差进行操作后,到最后,其实无法确认这个全局变量真实的值到底是多少;

而且如果针对秒杀的问题的话,就会很容易出现超卖的情况;所以针对这个问题,我们后面需要对进行操作的代码块进行锁住;只开放一个线程对这个代码快进行操作;这样就会避免多个线程同一时间对同一个变量做操作;

简单秒杀:

        

package duoxiancheng;

public class TicketCell implements Runnable {
	private int tickets = 100;

	@Override
	public void run() {
		while (true) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + ":正在出售第" + tickets + "张票");
					tickets--;
			}

		}

	}

}

package duoxiancheng;

public class TicketCellDemo {

	public static void main(String[] args) {
		TicketCell t=new TicketCell();
		Thread t1=new Thread(t, "窗口1");
		Thread t2=new Thread(t, "窗口2");
		Thread t3=new Thread(t, "窗口3");
		t1.start();
		t2.start();
		t3.start();
		

	}

}

 执行结果:

我们发现这边可能有出现票为负值的情况,说明出现了超卖;

可能还有出现三个窗口在卖同一张票的情况;

所以这样很容易出现问题:

为了解决这个问题 ,我们需要对全局变量操作的代码块进行锁定;这个时候就需要用到synchronized(new Object())对对象进行锁定;这个里面的对象一定需要设定好,固定住,不然到时候线程进入后,都会重新去创建对象,

        

package duoxiancheng;

public class TicketCell implements Runnable {
	private int tickets = 100;

	@Override
	public void run() {
		while (true) {
			//synchronized (ob)中必须为同一个对象,不然每个线程都是new一个对象,其实最后是没有任何效果
			synchronized (new Object()) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + ":正在出售第" + tickets + "张票");
					tickets--;
				}
			}

		}

	}

}

执行结果:

我们会发现,这边就算使用了synchronized对代码快进行锁定,但是他的结果还是会出现超卖的情况:为什么呢???

        因为synchronized(new Object())这边在new对象的时候,在每个线程进来时,都会新new一个对象,那就不是对同一个对象操作;所以他的最后结果其实是没有任何的效果

        在这边写时,我们需要进行设定一个统一的对象,后续线程都对这个对象进行操作,就不会出现以上的问题:

        ,

package duoxiancheng;

public class TicketCell implements Runnable {
	private int tickets = 100;
	private Object ob = new Object();

	@Override
	public void run() {
		while (true) {
			//synchronized (ob)中必须为同一个对象,不然每个线程都是new一个对象,其实最后是没有任何效果
			synchronized (ob) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + ":正在出售第" + tickets + "张票");
					tickets--;
				}
			}

		}

	}

}

 按照以上这种写法,就可以避免之前所出现的问题了


版权声明:本文为weixin_42352733原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。