0
点赞
收藏
分享

微信扫一扫

6.线程的同步代码块&&同步方法

言诗把酒 2022-03-17 阅读 40

前面的买火车票的案例的代码存在线程安全问题

问题1:多个线程抢票出现相同的票数

问题2:出现错误票数,如:0,-1,-2等

原因:多个线程,在争抢资源的过程中,导致共享的资源出现问题,一个线程还没执行完,另一个线程就参与进来了,开始争抢

解决:在我的程序中,加入"锁"-->加同步-->同步监视器

方法1.同步代码块

实现Runnable接口

public class BuyTicketThread implements Runnable{
    int ticketNum=10;
    @Override
    public void run() {
        for (int i=1;i<=100;i++) {
            synchronized (this) {//把具有安全隐患的代码锁住,如果锁多了就会效率低-->this 就是这个锁
                if (ticketNum > 0) {
                    System.out.println("我在" + Thread.currentThread().getName() + "买到了" + (ticketNum--) + "票");
                }
            }
        }
    }
}

Thread

public class BuyTicketThread extends Thread{
    static int ticketNum=10;
    @Override
    public void run() {
        for (int i=1;i<=100;i++) {
            synchronized (BuyTicketThread.class) {//锁必须多个线程用的是一把锁!!
                if (ticketNum > 0) {
                    System.out.println("我在" + Thread.currentThread().getName() + "买到了" + (ticketNum--) + "票");
                }
            }
        }
    }
}

同步方法

Thread

public class BuyTicketThread extends Thread{
    public BuyTicketThread(String name) {
        super(name);
    }

    //一共10张票 加上static 修饰 为多个对象共享10张票
   static int ticketNum=10;//每个窗口都是一个线程对象:每个对象执行的代码放入run方法中
    @Override
    public void run() {
        for (int i=1;i<=100;i++) {
                buyTicket();
            }
        }
        //没有static 修饰也是锁住当前对象但问题没解决,,static修饰 -->多个对象共享一个锁
        public static synchronized void buyTicket(){//锁住的是当前的这个对象this 同步监视器:BuyTicketThread.class
            if (ticketNum > 0) {
                System.out.println("我在" + Thread.currentThread().getName() + "买到了" + (ticketNum--) + "票");
            }
    }
}

Runnable

public class BuyTicketThread implements Runnable{
    int ticketNum=10;
    @Override
    public void run() {
        for (int i=1;i<=100;i++) {
                buyTicket();
            }
        }
        public synchronized void buyTicket(){ //锁住当前调用方法的对象this
            if (ticketNum > 0) {
                System.out.println("我在" + Thread.currentThread().getName() + "买到了" + (ticketNum--) + "票");
            }
    }
}

总结1:

1.多线程在争抢资源,就要实现线程的同步(就要进行加锁,并且这个锁必须是共享的,必须是唯一的,咱们的锁一般都是引用数据类型的.

目的:解决了线程安全问题

总结2:关于同步方法

1.不要将run()定义为同步方法

2.非静态同步方法的同步监视器是this
        静态同步方法的同步监视器是类名.class字节码信息对象

3.同步代码块的效率要高于同步方法

        原因:同步方法是将线程挡在了方法的外部,而同步代码块将线程挡在了代码的外部,但却是方法的内部

4.同步方法的锁是this,一旦锁住一个方法,就锁住了所有的同步方法;

        同步代码块只是锁住使用该同步监视器的代码块,而没有锁住使用其他监视器的代码块

举报

相关推荐

0 条评论