zoukankan      html  css  js  c++  java
  • 线程安全问题

    /*
     需求: 模拟3个窗口同时在售50张 票 。
     
    问题1 :为什么50张票被卖出了150次?
    
    出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。
    
    解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。
    
    问题2: 出现了线程安全问题 ?
    
    线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。
        
        java线程同步机制的方式:
        
            方式一:同步代码块
                
                同步代码块的格式:
                    
                    synchronized(锁对象){
                        需要被同步的代码...
                    }
    
    同步代码块要注意事项:
            1. 任意的一个对象都可以做为锁对象。
            2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
            3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
            4. 多线程操作的锁 对象必须是 唯一共享的。否则无效。
     synchronized (new Object()) { } 无效
    
    
    synchronized ("锁") { } 有效,
    "锁"被创建后,不会再被创建了。
    5. 一个线程在同步代码块中sleep了,并不会释放锁对象。

               6. 如果不存在着线程安全问题,千万不要使用同步代码块,因为会降低效率。


    出现线程安全问题的根本原因: 1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。 2. 有多个语句(两句及以上)操作了共享资源。(执行到一半,cpu执行权被抢走)
    */ class SaleTicket extends Thread{ static int num = 50;//票数 非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。 static Object o = new Object(); public SaleTicket(String name) { super(name); } @Override public void run() { while(true){ //同步代码块 synchronized ("锁") { if(num>0){ System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } num--; }else{ System.out.println("售罄了.."); break; } } } } } public class Demo4 { public static void main(String[] args) { //创建三个线程对象,模拟三个窗口 SaleTicket thread1 = new SaleTicket("窗口1"); SaleTicket thread2 = new SaleTicket("窗口2"); SaleTicket thread3 = new SaleTicket("窗口3"); //开启线程售票 thread1.start(); thread2.start(); thread3.start(); } }

    如果采用第二种方式创建多线程,则不用static修饰num。因为只传了一个对象。

    class SaleTicket implements Runnable{
        
        int  num = 50; // 票数
        
        @Override
        public void run() {
            while(true){
                synchronized ("锁") {
                    if(num>0){
                        System.out.println(Thread.currentThread().getName()+"售出了第"+ num+"号票");
                        num--;
                    }else{
                        System.out.println("售罄了..");
                        break;
                    }    
                }
            }        
        }
    }
    
    public class Demo4 {
        
        public static void main(String[] args) {
            //创建了一个Runnable实现类的对象
            SaleTicket saleTicket = new SaleTicket();
            //创建三个线程对象模拟三个窗口
            Thread thread1 = new Thread(saleTicket,"窗口1");
            Thread thread2 = new Thread(saleTicket,"窗口2");
            Thread thread3 = new Thread(saleTicket,"窗口3");
            //开启线程售票
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }
  • 相关阅读:
    redhat 6.4下PXE+Kickstart无人值守安装操作系统
    ubuntu14.04安装好Hadoo之后接着安装hbase和介绍常用命令
    避坑之Hadoop安装伪分布式(Hadoop3.2.0/Ubuntu14.04 64位)
    kindeditor文件上传设置文件说明为上传文件名(JSP版)
    sqlmap 扫描注入漏洞
    局域网内访问不同网段的主机(转记)
    cmd创建用户开启3389命令
    用python来更改windows开机密码
    代码安全之上传文件
    web渗透(转)
  • 原文地址:https://www.cnblogs.com/thiaoqueen/p/6580890.html
Copyright © 2011-2022 走看看