Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么

Posted Acmen-zym

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么相关的知识,希望对你有一定的参考价值。

简述

程序的结构
一个程序读入内存时,全部由0合1组成的(初代计算机是由电路配合灯泡进行处理的,0表示关闭1表示开启),从内存读入到CPU处理,需要通过总线;
总线的类型
总线分为三种:控制线、地址线、数据线;

执行流程大概是

执行文件读入内存 --》找到进程main地址 --》逐步读出指令与数据 --》处理并且写回内存

进程与线程

进程:一个程序是可以有多个进程的,进程与进程之间的内存资源相互隔离的,无法直接获取。
总体概念是静态:进入内存后,分配对应的内存空间,同时产生一个主线程;
线程:线程是建立在进程之下的,多个线程可以共享同一个进程下的内存空间;
线程概念是动态:可执行的计算单元,线程是一条一条的指令,资源都是在进程中的;

为什么不用多个进程实现多线操作?
如果允许进程之间直接共享内存就会导致安全性变低,如下案例:
1、A程序直接读B程序中内存资源,获取B程序的账号密码;
2、A程序直接编写入侵代码,让B程序内存资源崩溃导致B程序直接关闭;

线程上下文的切换流程
1、挂起一个线程,然后将这个线程在CPU中的状态信息,也就是上下文信息保存到缓存中;
2、在缓存中检索下一个线程的上下文并将其在CPU的寄存器中恢复;
3、跳转到程序计数器所指向的位置,也就是跳转到线程被中断时代码执行的位置,并恢复该线程的执行;

Java线程与不安全

以上描述一个进程可以理解为一个资源容器,当一个进程中的内存资源,可以被多个线程修改时则为不安全的。CPU的速度是远超内存的,并且CPU会碎片化执行处理,让所以线程都可以争抢CPU使用资源;
1、多个线程使用内存中同一个值进行计算,因为线程是异步执行的,也就会出现这个值在某个阶段被多次使用,导致最终计算数据不准确;
2、多个服务中根据同一个值进行计算,由于服务之间也是异步执行的,也会导致这个值在某个阶段被多次使用,导致最终计算数据不准确;

案例代码如下,下方代码就会出现多个线程拿到相同值进行计算

 private static int num = 0;

    public static void main(String[] args) throws InterruptedException 

        for (int i = 0; i <= 100; i++) 
            new Thread(new Count()).start();
        
        //因为是线程异步执行所以需要休眠等待执行完毕
        Thread.sleep(8000);
    

    static class Count implements Runnable 
        @Override
        public void run() 
            String name = Thread.currentThread().getName();
            try 
                //随机休眠毫秒数,模拟业务处理场景
                Thread.sleep(new Random().nextInt(80) + 50);
             catch (InterruptedException e) 
                e.printStackTrace();
            

            ++num;
            System.out.println("name = " + name + " num = " + num);
        
    

此代码打印结果是无法保证最终num值为100的,每次执行都可能会是不同的效果

Java线程安全

说明一下共享第三方资源也会有并发安全隐患,本次只描述进程中内存资源的情况;
1、不于进程内多个线程共享变量资源,则可以认定为安全可靠操作;
2、变量参数只会有一个主线程进行修改,其他线程只负责读取,则也是安全的;
3、利用锁或者原子类进行资源管理,达到线程安全
4、远程服务使用相同数据做处理时用分布式锁,达到并发尽可能安全,分布式可靠性个人感觉是做不到百分之百的
如下案例代码,此代码不管多少线程执行最终都是同一个值

    private static AtomicInteger num = new AtomicInteger();

    public static void main(String[] args) throws InterruptedException 

        for (int i = 0; i <= 100; i++) 
            new Thread(new Count()).start();
        
        //因为是线程异步执行所以需要休眠等待执行完毕
        Thread.sleep(8000);
    

    static class Count implements Runnable 
        @Override
        public void run() 
            String name = Thread.currentThread().getName();
            try 
                //随机休眠毫秒数,模拟业务处理场景
                Thread.sleep(new Random().nextInt(80) + 50);
             catch (InterruptedException e) 
                e.printStackTrace();
            
            int andIncrement = num.getAndIncrement();
            System.out.println("name = " + name + " num = " + andIncrement);
        
    

因为是多线程的情况,会出现打印顺序无规律,但是最终num的值肯定是100

以上是关于Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程,线程安全与不安全的理解,程序的多线程并发编程的基础概念,进程与线程的区别是什么

Java线程:线程安全与不安全

java中的StringStringBufferStringBuilder的区别

再次理解多线程线程安全问题(理解java内存模型后)

Java并发编程学习:线程安全与锁优化

多线程加强