zoukankan      html  css  js  c++  java
  • 线程安全的3种方式

    1 多线程容易出现问题

    举个例子,电影院卖票,一共卖100张票,分3个窗口,用多线程来模拟,看会发生什么?

    1-1 创建一个卖票任务,实现Runnable接口

    public class Ticket implements Runnable{
    
    //    总共100
        private int ticket = 100;
    
        @Override
        public void run() {
            while (true){
                if (ticket>0){
                    try {
    //                    处理卖票耗时
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    String name = Thread.currentThread().getName();
                    System.out.println(name+"正在卖票"+ticket--);
                }
            }
    
        }
    }
    
    

    1-2 创建3个线程,来卖票

    public class Test {
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
            Thread t1 = new Thread(ticket, "线程1");
            Thread t2 = new Thread(ticket, "线程2");
            Thread t3 = new Thread(ticket, "线程3");
    
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    

    1-3 出现的问题

    • 相同的票被卖了2次,如下图
      屏幕快照 2020-03-12 下午10.08.33.png
    • 不存在的票,如0或者1
      屏幕快照 2020-03-12 下午10.09.42.png
      若有多个线程同时执行写的操作,那么需要考虑线程同步,否则的话,可能影响线程安全。

    2 同步代码块 synchronized

    synachronized(同步锁){
              需要同步操作的代码
    }
    

    2-1 使用同步锁的方式来创建Runnable的实现类

    public class Ticket implements Runnable{
    
    //    总共100
        private int ticket = 100;
    
        Object obj = new Object();
    
        @Override
        public void run() {
            while (true){
                synchronized (obj){
                    if (ticket>0){
                        try {
    //                    处理卖票耗时
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        String name = Thread.currentThread().getName();
                        System.out.println(name+"正在卖票"+ticket--);
                    }
                }
            }
    
        }
    }
    
    

    3 使用同步方法来解决线程安全

    使用synchronized修饰的方法,就是同步方法,可以保证一个线程执行该方法的同时,其它的线程只能在方法的外边等候

    public class Ticket implements Runnable{
    
    //    总共100
        private int ticket = 100;
    
    
        @Override
        public void run() {
            while (true){
                sellTicket();
            }
    
        }
    
        public synchronized void sellTicket(){
            if (ticket>0){
                try {
    //                    处理卖票耗时
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String name = Thread.currentThread().getName();
                System.out.println(name+"正在卖票"+ticket--);
            }
        }
    }
    
    

    4 使用lock锁

    synachronized(同步锁){
              需要同步操作的代码
    }
    

    2-1 使用同步锁的方式来创建Runnable的实现类

    public class Ticket implements Runnable{
    
    //    总共100
        private int ticket = 100;
    
    Lock lock = new ReentrantLock();    
    
        @Override
        public void run() {
            while (true){
                lock.lock();
                 if (ticket>0){
                        try {
    //                    处理卖票耗时
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        String name = Thread.currentThread().getName();
                        System.out.println(name+"正在卖票"+ticket--);
                    }
                  lock.unlock();
           }
    
        }
    }
    
    
  • 相关阅读:
    Intellij idea安装
    c# .net 我的Application_Error 全局异常抓取处理
    c# .net Global.asax文件的作用
    ASP.NET机制详细的管道事件流程(转)
    正则表达式_学习笔记
    c# .net获取随机字符串!
    c# 动态调用WCF方法笔记!
    Web Service和WCF的区别。其实二者不属于一个范畴!!!
    c# .net获取文件夹下的所有文件(多层递归),并获取区间数据(Jsion,xml等数据)写出到处理文件,学习分享~
    c#.net单例模式的学习记录!
  • 原文地址:https://www.cnblogs.com/hellosiyu/p/12483304.html
Copyright © 2011-2022 走看看