zoukankan      html  css  js  c++  java
  • java 多线程安全问题-同步代码块

    /*
    多线程的安全问题:
            while(true)
            {
                if(tick>0)
                {   
                    //线程0,1,2,3在余票为1时,都停滞在这里,之后分别获得CPU执行权,打印出0,-1,-2等错票
                    System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
                }
            }
    
    问题的原因:
        当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行一部分,还没有执行完,停滞
        另一个线程参与进来执行,导致共享数据错误。
    
    解决办法:
        对多条操作共享数据的语句块,进行限制,每次只允许一个线程执行,执行完毕后,再运行其它线程执行
    
    ----
    java对于多线程的安全问题提供了专业的解决方式
    同步代码块: 
            synchronized(对象)
            {
                需要同步的代码
            }
    (个人理解锁:锁就是一个不停在0,1变化的标志位,根据真假判断可选择是否进入操作区域。操作系统中的元量知识
                  对象就类似标志位
                  初始时为1,当线程进入后首先使标志位自减为0
                  假设此时线程停滞了,由于标志位为0,其他线程也进不来
                  当线程唤醒执行完毕后,又将标志位置1,允许别的进程进入
    )
    类似火车上的卫生间: 有人(1) 无人(0)
    
    对象如同锁。持有锁的线程可以在同步中执行
    没有持有锁的线程即使获得CPU的执行权,也无法进入,因为没有获取锁
    
    -----
    同步的前提:
    1. 必须要有两个或者两个以上的线程
    2. 必须是多个线程使用同一个锁
    
    必须保证同步中只能有一个线程在执行
    
    ---
    同步机制
    好处:解决了多线程的安全问题
    弊端:多个线程每次都要判断锁,较为消耗资源
    
    */
    class Ticket implements Runnable
    {
        private int ticket =1000;
        Object obj = new Object(); //使用上帝创建对象
        public void run()
        {
            while(true)
            {
                synchronized(obj)
                {
                    if(ticket>0)
                    {
                        System.out.println(Thread.currentThread().getName()+"....余票可卖数 : "+ ticket--);
                    }
                }    
            }
    
        }
    
    }
    class  TecketDemo2
    {
        public static void main(String[] args) 
        {
            Ticket t =new Ticket();
    
            Thread t1= new Thread(t);
            Thread t2= new Thread(t);
            Thread t3= new Thread(t);
            Thread t4= new Thread(t);
            
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            System.out.println("Hello World!");
        }
    }
  • 相关阅读:
    C#中的静态
    C#类的使用
    C#接口实现多态
    C#---->类和接口
    winform项目导入数据
    kms访问数据库的方式(该篇只是作为个人笔记,不具有任何公共参考意图)
    win7下安装docker toolbox
    JabRef:将bibtex格式的参考文献导入EndNote的转换软件
    RabbitMQ安装以及简单操作应用(针对Windows和C#)
    C# Task和异步方法
  • 原文地址:https://www.cnblogs.com/shuqingstudy/p/4947696.html
Copyright © 2011-2022 走看看