synchronized

问题遇到的现象和发生背景

synchronized应该没问题吧,是没有共享num值?,但是设置了static还是没用?

用代码块功能插入代码,请勿粘贴截图
public class ticketSell {
    public static void main(String[] args) {
        ticket ticket = new ticket();
        ticket ticket1 = new ticket();
        ticket ticket2 = new ticket();
        ticket.start();
        ticket1.start();
        ticket2.start();
    }
}

class ticket extends Thread {
    public static int num = 100;
    boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            sell();
        }
    }

    public synchronized void sell() {
        if (num <= 0) {
            loop = false;
            System.out.println("售票结束");
            return;
        }
        System.out.println(Thread.currentThread().getName() + "-窗口:卖出一张票,还剩:" + (--num));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果及报错内容

img

问题很明显,你的同步方法要是静态的,即public static synchronized修饰,因为你是用Thread创建多线程,此时,你创建了线程三个对象,如果你这个同步方法没有用static修饰,那么,这个同步锁就是this,你创建了三个对象,this不唯一,即同步锁不唯一,所以同步失败,加上static之后你的同步锁就是ticket.class,同步🔒唯一。
用Runnable创建多线程这不会出现这个情况!

多线程掌握不好,请看我这两篇博文:
http://t.csdn.cn/bNV50
http://t.csdn.cn/bMVqL
内含多线程总结以及不同多线程对卖票案例的实现。
有帮助的话采纳一下哦!

看看我举的这个例子,你就明白了


/**
 *  线程同步之同步代码块和同步方法
 * */
public class ThreadSynchronization {
    public static void main(String[] args) {
        Ticket2 ticket2=new Ticket2();
       new Thread(ticket2,"窗口1").start();
        new Thread(ticket2,"窗口2").start();
        new Thread(ticket2,"窗口3").start();
        new Thread(ticket2,"窗口4").start();
    }
}
/**Ticket1类实现Runnable接口*/
class Ticket1 implements Runnable{
    private int tickets=10;
    //定义任意一个对象,用作同步代码块的锁
    Object lock=new Object();
    @Override
    public void run() {

        while(true){
            /**定义同步代码块*/
            synchronized (lock){
            try{Thread.sleep(10);}
            catch (InterruptedException e)
            {e.printStackTrace();}
            if(tickets>0) {
                //获取当前线程
                Thread th = Thread.currentThread();
                //获取当前线程的名字
                String th_name = th.getName();
                System.out.println(th_name + "正在发售第" + tickets-- + "张票");
            }else{break;}//如果tickets小于0,跳出循环
        }
        }
    }
}
/**Ticket2类实现Runnable接口*/
class Ticket2 implements Runnable{
    private int tickets=10;
    public void run() {
        while(true){
            //调用售票方法
            saleTicket();
            if(tickets<=0){break;}
        }
    }
    //定义一个同步方法saleTicket(),锁的是this
    private synchronized void saleTicket(){
        if(tickets>0)
        {
            try{Thread.sleep(10);}//经过此处线程休眠10毫秒
            catch (InterruptedException e){e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+"---卖出的票号"+tickets--);
        }
        }
}

同步方法实现的:

img


同步代码块实现的:

img

不知道你解决了没有?我这也添加点见解。
你目前的情况是不理解synchronized和static的作用域,
如果你理解了,或许你会更清楚。
1、样例代码,前面回答有了;
2、理论,前面也有了;
3、可能你不理解,你看看是否需要有人手把手说明。