项目中,我们经常会遇到一些秒杀情况:例如:我们就只有一定量的票数量;这个时候有多个窗口进行售卖;
这个时候其实就是多个线程对一个变量进行操作;这样很容易出现,当第一个线程在对全局变量进行操作时,另外一个进程也进来对变量进行操作;这样有一些时间差进行操作后,到最后,其实无法确认这个全局变量真实的值到底是多少;
而且如果针对秒杀的问题的话,就会很容易出现超卖的情况;所以针对这个问题,我们后面需要对进行操作的代码块进行锁住;只开放一个线程对这个代码快进行操作;这样就会避免多个线程同一时间对同一个变量做操作;
简单秒杀:
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版权协议,转载请附上原文出处链接和本声明。