• 同步代码块和同步方法案例实战


    什么是同步

    • 同步就是加锁,不让其它人访问
    • synchronized指的就是同步的意思

    什么情况下需要同步

    当多线程并发, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步,否则会有线程安全问题。

    同步代码块

    • 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
    • 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
    • 使用同步锁时,应该尽是让锁的范围小点,才能提高性能

    同步代码块案例:

    package demo;
    
    public class Task implements Runnable{
        private int tickets = 100;
        public void run(){
            while(true){
                synchronized (this){
                    if(tickets <= 0){
                        System.out.println("不好意思,票卖完了");
                        break;
                    }else{
                        System.out.println(Thread.currentThread()+"恭喜你买到票,票号"+tickets);
                        tickets--;
                    }
                }
            }
        }
    }
    package demo;
    
    public class SynchronizedDemo {
        public static void main(String[] args) {
            Task task = new Task();
            Thread t1 = new Thread(task);
            Thread t2 = new Thread(task);
            Thread t3 = new Thread(task);
            t1.start();
            t2.start();
            t3.start();
        }
    }

    同步方法

    • 使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
    • 非静态同步方法的锁是:this
    • 静态同步方法的锁是:字节码对象(xx.class)

    案例:卖火车票

    • 需求,有ABCD4个窗口同时买票,只有100张票可买
    • 多线程会有安全问题熟记
        //火车站卖票【问题】
            /**
             * 湖南到广州火车票:今天13:00 ,100张
             * 火车站有4个窗口在同时卖票,要保证一张票只能被卖一次
             * 
             * 搞4个线程表示4个窗口
             * 
             * 通过加锁可以解决被多次卖同一张票的问题
             * 
             * 使用同步代码块
             */
            
            //创建卖票的任务
            TicketTask task = new TicketTask();
            
            //A窗口
            Thread t1 = new Thread(task);
            t1.setName("窗口A");
            //B窗口
            Thread t2 = new Thread(task);
            t2.setName("窗口B");
            //C窗口
            Thread t3 = new Thread(task);
            t3.setName("窗口C");
            //D窗口
            Thread t4 = new Thread(task);
            t4.setName("窗口D");
            
            //开启线程
            t1.start();
            t2.start();
            t3.start();
            t4.start();
    class TicketTask implements Runnable{
        //只有100张票
        int ticket = 100;
        @Override
        public synchronized void run() {
            //卖票
            while (true) {
                if (ticket <= 0) {
                    System.out.println("不好意思,票已经卖完了...");
                    break;
                } else {
                    System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket);
                    ticket--;
                }
            }
        }
        
        /*@Override
        public void run() {
            // TODO Auto-generated method stub
            *//**
             * 同步代码换括号里参数可以传任意对象
             * this是一个锁对象
             * 不同的一把锁,卖相同的票总是还是存在
             *//*
            
            //卖票
            while (true) {
                synchronized (String.class) {// 同步:加锁
                    if (ticket <= 0) {
                        System.out.println("不好意思,票已经卖完了...");
                        break;
                    } else {
                        System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket);
                        ticket--;
                    }
                }
            }
        }*/
        
        /*@Override
        public void run() {
            // TODO Auto-generated method stub
            *//**
             * 同步代码换括号里参数可以传任意对象
             *//*
            synchronized (this) {
                //卖票
                while(true){
                    if(ticket <= 0){
                        System.out.println("不好意思,票已经卖完了...");
                        break;
                    }else{
                        System.out.println(Thread.currentThread() + "恭喜你卖到票,票号" + ticket);
                        ticket --;
                    }
                }
            }
        }*/
    }
  • 相关阅读:
    .Net时间计算函数,统计某一天是一年的第几周,这一周从哪天开始到哪天结束
    1分钟搞定超慢SQL
    网站
    舞台
    相见欢
    一套完整系统对人生的意义
    2015/08/15心情
    Linux下压缩某个文件夹(文件夹打包)
    init进程 && 解析Android启动脚本init.rc && 修改它使不启动android && init.rc中启动一个sh文件
    andriod系统裁剪心得
  • 原文地址:https://www.cnblogs.com/ivan5277/p/10159605.html
Copyright © 2020-2023  润新知