首页 > 其他分享 >线性安全和非线性安全的区别

线性安全和非线性安全的区别

时间:2023-03-10 16:22:06浏览次数:32  
标签:count 变量 ++ 非线性 安全 线程 内存 线性 public

线性安全:就是当多线程访问时,采用了加锁的机制;即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能访问,直到这个线程读取完之后,其他线程才可以使用,防止出现数据不一致或者数据被污染的情况。

非线性安全(线性不安全):就是不提供数据访问时的数据保护,多个线程可以同时操作某个数据,从而出现数不一致或者数据污染的情况。

简单的去理解就是,线性安全是多线程操作同一个对象不会出现问题,非线性安全(线性不安全)是多线程操作同一个对象 可能 会出现问题。

 

存在线程安全问题必须满足三个条件:

1.多线程

2.有共享变量

3.对共享变量有修改操作

 

线程安全工作原理:

jvm中有一个Main Memory,每一个线程也有自己的Working Memory,一个线程对于一个变量variable进行操作的时候,都需要在自己的Working Memory里创建一个变量的副本copy,操作完之后再写入Main Memory。也就是说,当多线程操作同一个变量variable,可能会出现不可预知的后果。

------------------------------

1.主内存(Main Memory)

主内存可以理解为计算机中的内存,但是又不完全相同。主内存被所有线程共享(比如静态变量,或者堆内存)来说,内存当中存储了他的“本尊”。
2.工作内存(Working Memory)

工作内存可以简单理解为计算机中的CPU高速缓存,但又不完全相同。每一个线程拥有自己的工作内存,对于一个共享变量来说,工作内存当中存储了他的“副本”。

 

线程对共享变量的所有操作都必须在工作内存进行,不能直接读写主内存中的变量。不同线程之间也无法访问彼此的工作内存,变量值的传递只能通过主内存来进行。

例子:开启10个线程,每个线程当中让静态变量count自增100次之后。执行之后会发现,最终count的结果值未必是1000,有可能是小于1000.(这里count是线程间的共享变量)

public class Test {
    public static int count = 0;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //开启10个线程
        for(int i = 0; i < 10; i++){
            new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                Thread.sleep(1);
                            }
                            catch(InterruptedException e){
                                e.printStackTrace();
                            }
                            //每个线程中让count自增100次
                            for(int j = 0; j < 100; j++){
                                count++;
                            }
                        }
                    }).start();
        }
        try{
            Thread.sleep(2000);
        }
        catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("count= "+count);
    }
}
//运行结果:count= 952
假设count=2时,当线程1在将count++的结果(count=3)写入内存之前,线程2已经从内存中读取了count的值,并在这个值(count=2)上进行++操作,先于线程1将count=3写入了内存,这是线程1再将count=3写入内存,就存在错误了。
使用synchronized同步方法改进:
public class VolatileTest {
    public static int count = 0;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // 开启10个线程
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // 每个线程中让count自增100次
                    for (int j = 0; j < 100; j++) {
                        count(); //count++;
                    }
                }
            }).start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("count= " + count);
    }

    public static synchronized void count() {
        count++;
    }
}
运行结果:
count=1000

java中实现线程安全的方法:
1.最简单的方法,使用synchronization关键字
用synchronized的关键是建立一个监控,这个monitor可以是要修改的变量,也可以是其他自己认为合适的对象(方法),然后通过给这个monitor加锁来实现线程安全,每个线程在获得这个锁之后,要执行加载(load)到working memory在到使用(use)&&指派(assign)到
存储(store)再到main memory的过程。才会释放他得到的锁。这样就实现了所谓的线程安全。

 2.使用java.util.concurrent.atomic包中的原子类,例如AtomicInteger

3.使用java.util.concurrent.locks包中的锁

4.使用线程安全的集合ConcurrentHashMap

5.使用volatile关键字,保证变量的可见性(直接从内存读,而不是从线程catch读)

 

---------------------------------

内容来源:https://www.cnblogs.com/zeroingToOne/p/9524543.html

标签:count,变量,++,非线性,安全,线程,内存,线性,public
From: https://www.cnblogs.com/dengliming/p/17203148.html

相关文章

  • K8S的安全机制
    前言:机制Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。APIServer是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes......
  • 线程安全的map
    实现多线程下的insertfinderasebeginend等操作,输入的key或者value为指针的时候可以根据输入的releasefu回调实现内存释放/****************************************......
  • 【机器学习】1. 广义线性模型
    1.广义线性模型1.1从简单线性回归开始机器学习的任务是从已知的数据中提取知识,从而完成对新数据的识别与预测,即应用知识.但是,数据本身不会给予研究者想要的答案......
  • 外汇天眼:在使用外汇EA时,如何做才能让交易更安全?
    外汇EA是使用MQL4编程语言,针对MetaTrader交易平台编写的自动交易程序。在这里交易员能够将自身的交易经验和交易策略编写到EA程序中,EA的使用者能够依照既定的EA程序进行自......
  • 分布式架构-可靠通讯-服务安全
    引子上一节“分布式架构-可靠通讯-零信任网络”里,我们探讨了与微服务运作特点相适应的零信任安全模型。本节,我们将从实践和编码的角度出发,介绍在前微服务时代(以SpringCl......
  • ACP云原生容器工程师 - 安全管理
    阿里云容器服务ACK安全体系阿里云容器服务Kubernetes版安全体系提供从基础设施到上层用户业务应用全链条安全体系支撑支持运行时刻的安全策略管理,应用安全配置巡......
  • FinOps首次超越安全成为企业头等大事|云计算趋势报告
    随着云计算在过去十年中的广泛应用,云计算用户所面临的一个持续不变的趋势是:安全一直是用户面临的首要挑战。然而,这种情况正在发生转变。 知名IT软件企业Flexera对云计......
  • FinOps首次超越安全成为企业头等大事丨云计算趋势报告
    随着云计算在过去十年中的广泛应用,云计算用户所面临的一个持续不变的趋势是:安全一直是用户面临的首要挑战。然而,这种情况正在发生转变。 知名IT软件企业Flexera对云计......
  • ssh命令 – 安全的远程连接服务器
    ssh命令–安全的远程连接服务器–Linux命令大全(手册)(linuxcool.com)语法格式:ssh[参数]远程主机常用参数:参数解释-p<端口>指定远程服务器上的端口......
  • 使用 Kryo 完成 序列化和反序列化,并使用ThreadLocal解决线程不安全问题
    (目录)基于kryo完成序列化和反序列化1.Kryo的使用Step01:定义mail类:packagecom.java.serializable;importjava.io.Serializable;importjava.util.Date;pub......