• 线程安全-001


    例子程序:

    /**
     * 多个线程一把锁
     * @author dev
     *
     */
    public class MyThread extends Thread{
        
        private int count = 5;
    
        //synchronized
        @Override
        public void run() {
            count--;
            System.err.println(this.currentThread().getName() + " count = "+count);
        }
        
        public static void main(String[] args) {
            
            /**
             * 多个线程访问myThread的run方法时,以排队的方式进行处理(CPU分配的先后顺序排队)
             * 一个线程想要执行synchronized修饰的方法里的代码:
             * 1,尝试获得锁
             * 2,如果拿到该锁,执行synchronized代码体内容,拿不到锁,这个线程就会不断尝试获得这把锁,
             * 直到拿到未止,而且是多个线程同时去竞争这把锁(也就是有锁竞争的问题)
             * 
             */
            
            MyThread myThread = new MyThread();
            //参数:Runnable target, String name
            Thread t1 = new Thread(myThread,"t1"); 
            Thread t2 = new Thread(myThread,"t2");
            Thread t3 = new Thread(myThread,"t3");
            Thread t4 = new Thread(myThread,"t4");
            Thread t5 = new Thread(myThread,"t5");
        
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            t5.start();    
        }
    }
    代码说明:
    MyThread继承Thread,是一个线程类,有一成员变量count,重写run方法:对count值进行减减,打印当前线程名字和count值。
    main方法:启动5个线程t1、t2、t3、t4、t5,把MyThread对象注入进去,启动5个线程。

    执行main方法,结果:

       线程启动后,5个线程都等待着cpu的执行,所以5个线程的执行顺序是随机的,导致看到的t1、t2 、t3、 t4、 t5的输出顺序是随机的。对于count值,我们心里预期的应该输出 count=4、count=3、count=2、count=1、count=0,但是输出结果跟心理预期的是不一样的。这就是说,5个线程同时访问MyThread类的run方法,对count值进行减减,不是线程安全的。

    将run方法加上synchronized 关键字,就是线程安全的:

    //synchronized加锁
        @Override
        public synchronized void run() {
            count--;
            System.err.println(this.currentThread().getName() + " count = "+count);
        }

    打印结果:

    这和我们心里的预期是一样的,也就是线程安全的。这就和开篇说的线程安全的定义:当多个线程访问某一个类(对象或者方法)时,这个类始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。这里的正确的行为,就是指你心里预期的。

     run方法 加上synchronized加锁后,启动5个线程,当第一个线程拿到锁后,其他4个线程就会等待,等着第一个线程释放锁,一次类推。

    多线程就是一个厕所,厕所门上有一个锁,外面5个人去抢这一把锁,谁抢到了锁,就可以进去上厕所,当第一个进去的出来后,其他4个人会同时去抢这把锁。所以会产生锁竞争的问题,当线程足够多的时候,锁竞争会导致CPU使用率过高,应尽量避免锁竞争。

     搞10000个线程,看看锁竞争cpu使用情况:

    代码:

    MyThread myThread = new MyThread();
            List<Thread> threads = new ArrayList<Thread>();
            for(int i=0;i<10000;i++){
                threads.add(new Thread(myThread,"t"+i)); 
            }
            for(Thread t : threads){
                t.start();
            }

    CPU:

    
    
    
    
  • 相关阅读:
    安卓目录分析——MainActivity.java和activity_main.xml
    安卓目录理解 —— AndroidMainifest.xml
    安卓教程列表
    安卓目录介绍
    ideal 安卓环境搭建
    ideal 2019激活 方法
    binding.gyp not found 安装java npm 报错
    vue-cli脚手架打包页面空白
    .java文件转为.class文件转jar包
    前端框架Vue自学之Vue基础语法(二)
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/10538698.html
Copyright © 2020-2023  润新知