synchronized(同步机制)

在之前售票系统(负票)版中,不管是用实现接口还是继承都有问题。

根本原因就是多个线程同时执行一个run()方法。

本次代码进行了改进,增加了synchronized。问题得到解决,详情看代码

实现互斥锁的步骤:

1.分析需要上锁的代码

2.选择同步代码块(建议使用,范围小,效率高)或同步方法

3.要求多个同步线程的锁对象为一个即可

tips:

同步方法(静态的)的锁为当前类本身

同步方法(非静态)的锁可以是this(注意区分new出来的对象是否为同一this),也可以是其他对象(要求是同一对象)


①synchronized加在方法上

package thread_;

public class TicketSystem {
    public static void main(String[] args) {
        TicketSystem02 ticketSystem02 = new TicketSystem02();
        new Thread(ticketSystem02).start();//第一个线程
        new Thread(ticketSystem02).start();//第二个线程
        new Thread(ticketSystem02).start();//第三个线程
    }
}

class TicketSystem02 implements Runnable{
    private  int ticketnum =100;//多个线程共享
    private Boolean loop = true;

    public void setLoop(Boolean loop) {
        this.loop = loop;
    }

    public synchronized void sell(){//同步方法,在同一时刻,只有一个线程执行sell()方法
        if (ticketnum<=0 ){//无票提示售罄
            System.out.println("售罄");
            setLoop(false);//执行到此会退出while循环
            return;
        }
        try {
            Thread.sleep(50);//有票间隔售卖时间 50ms
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
    }

    @Override
    public  void run() {//倘若在次写synchronized,则从头到尾只会由一个进程在售卖 
        while(loop){
            sell();
        }
    }
}

②synchronized代码块 在非静态方法中

package thread_;

public class TicketSystem {
    public static void main(String[] args) {
        TicketSystem02 ticketSystem02 = new TicketSystem02();
        new Thread(ticketSystem02).start();//第一个线程
        new Thread(ticketSystem02).start();//第二个线程
        new Thread(ticketSystem02).start();//第三个线程
    }
}
class TicketSystem02 implements Runnable{
    private  int ticketnum =100;//多个线程共享
    private Boolean loop = true;
    Object object = new Object();

    public void setLoop(Boolean loop) {
        this.loop = loop;
    }

    public  void sell(){
        synchronized(object/*this*/){//不仅可以用this,只要是同一对象即可
            if (ticketnum<=0 ){//无票提示售罄
                System.out.println("售罄");
                setLoop(false);
                return;
            }
            try {
                Thread.sleep(50);//有票间隔售卖时间 50ms
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
        }

    }

    @Override
    public  void run() {//synchronized 同步方法,在同一时刻,只有一个线程才能执行run()方法
        while(loop){
            sell();
        }
    }
}

 ③synchronized代码块 在静态方法中(代码有错误,只提供参考)

package thread_;

public class TicketSystem {
    public static void main(String[] args) {
        TicketSystem02 ticketSystem02 = new TicketSystem02();
        new Thread(ticketSystem02).start();//第一个线程
        new Thread(ticketSystem02).start();//第二个线程
        new Thread(ticketSystem02).start();//第三个线程
    }
}
class TicketSystem02 implements Runnable{
    private  int ticketnum =100;//多个线程共享
    private Boolean loop = true;
    Object object = new Object();

    public void setLoop(Boolean loop) {
        this.loop = loop;
    }

    public static void sell(){
        synchronized(TicketSystem02.class){//此时要用类名,因为互斥锁是加在类上的
            if (ticketnum<=0 ){//无票提示售罄
                System.out.println("售罄");
                setLoop(false);
                return;
            }
            try {
                Thread.sleep(50);//有票间隔售卖时间 50ms
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("窗口:"+Thread.currentThread().getName()+"售出一张票\t"+"还剩:"+(--ticketnum));
        }

    }

    @Override
    public  void run() {//synchronized 同步方法,在同一时刻,只有一个线程才能执行run()方法
        while(loop){
            sell();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值