zhou0773 发表于 2022-9-5 11:57

同步问题,卖票的一段代码

这是一个多线程的问题,是同时三个线程运行,进行卖票,但是到最后有可能出现同时两个或者三个线程进入到程序
导致多卖票,就使用了synchronized   同步,但是还是会出现多卖票问题,请大佬给看看哪里出现了问题
package com.dy.sym.Ticket;

/**
* @ClassName SellTicket03
* @AuThor 微笑
* @date 2022/9/5 11:03
* @Param
* @version 1.0
*/
public class SellTicket03 {
    public static void main(String[] args) {
      SellTicket04 sellTicket04 = new SellTicket04();
      new Thread(new SellTicket04()).start();
      new Thread(new SellTicket04()).start();
      new Thread(new SellTicket04()).start();



    }
}
class SellTicket04 implements Runnable{
    private static int sellTicket = 100;
    public boolean loop = true;
    public synchronized void sell(){//同步方法
      if (sellTicket <= 0){
            System.out.println("售票结束");
            loop = false;
            return;
      }
      try {
            Thread.sleep(50);
      } catch (InterruptedException e) {
            e.printStackTrace();
      }
      System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" +
                "剩余票数" + (--sellTicket));
    }
    @Override
    public void run() {

      while (loop){
         sell();
            }

      }
    }


coolcalf 发表于 2022-9-5 12:25

需要用到锁~网上有C#的这个例子

星月淘 发表于 2022-9-5 13:08

把sell方法放到runnable外面

jockiller 发表于 2022-9-5 13:16

本帖最后由 jockiller 于 2022-9-5 13:19 编辑

你的写法,同步加在了实例方法上。三个线程就是三个实例。。写到方法里面,然后把同步作用在类上就行了
synchronized (SellTicket04.class) {
            
}

不过即使这样,也仅仅能保证单机同步,建议直接用锁,将来升级分布式也方便。

你那个写法,通常用在静态方法,spring托管的单例对象上

lovejun 发表于 2022-9-5 13:30

synchronized写在非静态方法上,锁对象是this,也就是当前对象,你每次都new了一个SellTicket4实例,导致不是一个锁对象,而且loop也不是静态属性,每个实例中的loop完全不相关,想实现线程安全,就用同一个SellTicket4实例

10086abc 发表于 2022-9-5 14:48

大佬!学习了!

速度富贵浮云 发表于 2022-9-5 16:09

可以使用redis和MQ等中间件

layuai 发表于 2022-9-5 17:22

可以看看最近尚硅谷发布的分布式视频,很不错

sknbs 发表于 2022-9-6 10:24

这里synchronized锁的不是同一个对象,所以没有意义。。。

lsy_loren 发表于 2022-9-6 10:57

SellTicket04 sellTicket04 = new SellTicket04();
new Thread(new SellTicket04()).start();
new Thread(new SellTicket04()).start();
new Thread(new SellTicket04()).start();

// 改为

SellTicket04 sellTicket04 = new SellTicket04();
new Thread(sellTicket04).start();
new Thread(sellTicket04).start();
new Thread(sellTicket04).start();


页: [1]
查看完整版本: 同步问题,卖票的一段代码