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
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Acmen-zym

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值