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

什么是同步

  • 同步就是加锁,不让其它人访问
  • 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)

 

案例:卖火车票

  • 需求,有A\B\C\D4个窗口同时买票,只有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 --;
                }
            }
        }
    }*/
}

 

posted @ 2018-12-22 00:06  expworld  阅读(503)  评论(0编辑  收藏  举报