day23--电影院买票问题解决 同步代码块 同步方法 静态同步方法的引入

package cn.itcast_11;

/*
 * A:同步代码块的锁对象是谁呢?
 *         任意对象。
 *
 * B:同步方法的格式及锁对象问题?
 *         把同步关键字加在方法上。
 *
 *         同步方法的锁是谁呢?
 *             this(一个类本身对象就是this)
 *
 * C:静态方法及锁对象问题?
 *         静态方法的锁对象是谁呢?
 *             类的字节码文件对象。(反射会讲)
 */
public class SellTicketDemo {
    public static void main(String[] args) {
        // 创建资源对象
        SellTicket st = new SellTicket();

// 创建三个线程对象
        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");

// 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

package cn.itcast_11;

/**
*      本模块利用了同步代码块操作相同代码时,不管执行的位置在哪里,都会一样的效果,利用X%2==0的特点,将线程的路径分为两边,但前面说过,同步代码块操作相同代码时是不需要考虑位置,因为他们的锁是相同的特性,由此引出静态同步方法,与非静态同步方法。因为if与else内的效果是一样的,若效果不一样,说明两段代码锁的内容不一致,只要改成锁是相同的,就能达到效果一样从而说明同步方法,与静态同步方法需要哪种锁。
*/

/**
*     同步代码块:任意对象,但对象定义不能在代码块的括号内进行,不然每次都创建新对象维护锁,锁的意义失效
*     同步方法:本类内部对象:this,这个条件是隐含的。
*     静态同步方法:本类的.class 类对象,因为静态在类初始化前已经执行,所以普通的对象没用办法作为锁,因为static已经在它创建前创建好了,比static更早创建的类,只有类加载到方法区的Class类
*/
public class SellTicket implements Runnable {

// 定义100张票
    private static int tickets = 100;

// 定义同一把锁
    private Object obj = new Object();
    private Demo d = new Demo();

private int x = 0;
    
    //同步代码块用obj做锁
//    @Override
//    public void run() {
//        while (true) {
//            synchronized (obj) {
//                if (tickets > 0) {
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    System.out.println(Thread.currentThread().getName()
//                            + "正在出售第" + (tickets--) + "张票 ");
//                }
//            }
//        }
//    }
    
    //同步代码块用任意对象做锁
//    @Override
//    public void run() {
//        while (true) {
//            synchronized (d) {
//                if (tickets > 0) {
//                    try {
//                        Thread.sleep(100);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    System.out.println(Thread.currentThread().getName()
//                            + "正在出售第" + (tickets--) + "张票 ");
//                }
//            }
//        }
//    }
    
    @Override
    public void run() {
        while (true) {
            if(x%2==0){
                synchronized (SellTicket.class) {
                    if (tickets > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()
                                + "正在出售第" + (tickets--) + "张票 ");
                    }
                }
            }else {
//                synchronized (d) {
//                    if (tickets > 0) {
//                        try {
//                            Thread.sleep(100);
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                        System.out.println(Thread.currentThread().getName()
//                                + "正在出售第" + (tickets--) + "张票 ");
//                    }
//                }
                
                sellTicket();
                
            }
            x++;
        }
    }
//   表明任意类型都可以
//    private void sellTicket() {
//        synchronized (d) {
//            if (tickets > 0) {
//            try {
//                    Thread.sleep(100);
//            } catch (InterruptedException e) {
//                    e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName()
//                        + "正在出售第" + (tickets--) + "张票 ");
//            }
//        }
//    }
    
    //如果一个方法一进去就看到了代码被同步了,那么我就再想能不能把这个同步加在方法上呢?
//     private synchronized void sellTicket() {
//            if (tickets > 0) {
//            try {
//                    Thread.sleep(100);
//            } catch (InterruptedException e) {
//                    e.printStackTrace();
//            }
//            System.out.println(Thread.currentThread().getName()
//                        + "正在出售第" + (tickets--) + "张票 ");
//            }
//    }
    
    private static synchronized void sellTicket() {
        if (tickets > 0) {
        try {
                Thread.sleep(100);
        } catch (InterruptedException e) {
                e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                    + "正在出售第" + (tickets--) + "张票 ");
        }
}
}

class Demo {
}

时间: 2024-12-12 23:29:55

day23--电影院买票问题解决 同步代码块 同步方法 静态同步方法的引入的相关文章

区分同步代码块、静态同步方法、非静态同步方法的锁

同步代码块.静态同步方法.非静态同步方法的锁分别是: 同步代码块可以使用自定义的Object对象,也可以使用this或者当前类的字节码文件(类名.class): 静态同步方法的锁是当前类的字节码文件(类名.class): 非静态同步方法的锁是this: 证明方法: 两个线程之间实现同步,一个线程使用同步代码块,一个线程使用同步方法. 如果这两个线程同步了,说明了使用的是同一个锁: 创建线程类(以售票为例) /** * @methodDesc 售票线程类 */ public class Threa

线程的同步机制:同步代码块&同步方法

解决存在的线程安全问题:打印车票时出现重票,错票 使用同步代码块的解决方案 TestWindow2 package com.aff.thread; /* 使用实现Runnable接口的方式,售票 存在线程安全问题: 打印车票时出现重票,错票 1.原因:由于一个线程在操作共享数据过程中,未执行完毕的情况下, 另外的线程参与进来了,导致共享数据存在了安全问题 2.解决想法:让一个线程操作共享数据完毕后,其他进程才有机会参与共享数据的使用 3.java的解决方案: 线程的同步机制 方式一:同步代码块

同步方法和同步代码块

打个比方:一个object就像一个大房子,大门永远打开.房子里有很多房间(也就是方法).这些房间有上锁的(synchronized方法),和不上锁之分(普通方法).房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间.另外我把所有想调用该对象方法的线程比喻成想进入这房子某个房间的人.所有的东西就这么多了,下面我们看看这些东西之间如何作用的. 在此我们先来明确一下我们的前提条件.该对象至少有一个synchronized方法,否则这个key还有啥意义.当然也就不会有我们的这个主题了. 一个人

深入理解使用synchronized同步方法和同步代码块的区别

一.代码块和方法之间的区别 首先需要知道代码块和方法有什么区别: 构造器和方法块,构造器可以重载也就是说明在创建对象时可以按照不同的构造器来创建,那么构造器是属于对象,而代码块呢他是给所有的对象初始化的.底下看一个列子: public class Constructor_Methodblock { private int num; private String str; //构造器 public Constructor_Methodblock(int num,String str){ Syste

多线程之同步代码块与同步函数

/*需求:买票分析:多个窗口卖票 是并发的,是多线程利用Runnable接口,传入一个对象,开启多线程 */class Ticket implements Runnable{ private int num=100; Object obj=new Object(); public void run(){ while(true){ synchronized(obj) { if(num>0) { System.out.println(num--+Thread.currentThread().getN

JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程)把票陆陆续续的卖完了之后,我们要反思一下,这里面有没有安全隐患呢?在实际情况中,这种事情我们是必须要去考虑安全问题的,那我们模拟一下错误 package com.lgl.hellojava; import javax.security.auth.callback.TextInputCallback

java同步代码块

/** abc三个售票窗口,售50张票. 需求:可以做到同时销售,且不能卖重叠的,以及不能超过50 同步代码块 synchronized(对象){     同步代码块: } 对象如同锁,持有锁的线程可以在同步中执行 没有持有锁的线程即使获得CPU的执行器,也无法执行. 同步前提: 1.多线程的代码块才需要同步,即run里的代码才需要加同步.对共享数据加同步 2.必须是多个线程使用同一个锁,才需要同步 好处:提高多线程的安全问题 弊端:多个线程需要判断锁,较为消耗资源 */ class Tickt

Java线程安全与同步代码块

因为在电商网站工作的原因,对于秒杀.闪购等促销形式相当熟悉.无外乎商家拿出一定量的库存去做所谓的"亏本买卖",其目的是用有限的库存去吸引无限的流量.然而,我却碰到过因为系统问题,导致秒杀品超卖的情况.可怜的商户其实只提供了10双9.9元的童鞋做秒杀,却在瞬间内卖出了1000双! 类似这样的问题,在非线程安全的程序设计中十分常见,我们下面运行一个秒杀的程序: public class SalesThread implements Runnable { private int stock

多线程之同步代码块

class MyThreadimplements Runnable{ private int ticket = 6; @Override public void run(){ for(int i = 0;i < 10;i++){ synchronized(this){  //同步代码块 if(this.ticket>0){ try{ Thread.sleep(1000);  //线程休眠 }catch (InterruptedException e) { e.printStackTrace()