什么是线程安全
Posted 黑面书生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是线程安全相关的知识,希望对你有一定的参考价值。
如果这个是面试官直接问你的问题,你会怎么回答?
一个专业的描述是,
当多个线程访问一个对象时,如果不用进行额外的同步控制或其他的协调操作,调用这个对象的行为都可以获得正确的结果,我们就说这个对象是线程安全的
那么我们如何做到线程安全?
实现线程安全的方式有多种,其中在源码中常见的方式是,采用synchronized关键字给代码块或方法加锁,比如StringBuffer
那么,我们开发中,如果需要拼接字符串,使用StringBuilder还是StringBuffer?
场景一:
如果是多个线程访问同一个资源,那么就需要上锁,才能保证数据的安全性。
这个时候如果使用的是非线程安全的对象,比如StringBuilder,那么就需要借助外力,给他加synchronized关键字。或者直接使用线程安全的对象StringBuffer
场景二:
如果每个线程访问的是各自的资源,那么就不需要考虑线程安全的问题,
所以这个时候,我们可以放心使用非线程安全的对象,比如StringBuilder
比如在方法中,创建对象,来实现字符串的拼接。
看场景,如果我们是在方法中使用,那么建议在方法中创建StringBuilder,这时候相当是每个线程独立占有一个StringBuilder对象,不存在多线程共享一个资源的情况,所以我们可以安心使用,虽然StringBuilder本身不是线程安全的。
什么时候需要考虑线程安全?
1,多个线程访问同一个共享资源
2,资源是有状态的,比如我们上述讲的字符串拼接,这个时候数据是会有变化的
41-什么是线程安全?
其实说的是内存变量安全,如何理解?
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问, 直到该线程读取完,释放了锁,其他线程才可使用。
这样的话就不会出现数据不一致或者数据被污染的情况。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后
更改数据以至于所得到的数据是脏数据。这里的加锁机制常见的如:synchronized
局部变量一定是安全的,因为私有。
那成员变量呢,因为共享,就不安全,怎么办?
可以拷贝很多份,每个线程一份,比如,放到ThreadLocal<变量>
说的直白一些,就是把堆内存中的一个数据复制N份,
每个线程认领1份,同时规定好,每个线程只能玩自己的那 份,不准影响别人的。
需要说明的是这N份数据都还是存储在公共区域堆内存里的
ThreadLocal就是,把一个数据复制N份,
每个线程认领 一份,各玩各的,互不影响。
ThreadLocal是为每个线程创建一个单独的变量副本,每个线程都可以改变自己的变量副本而不影响其它线程所对应的副 本。
我理解的线程安全,就是,
一个共享变量,多个线程访问,在不通过额外加锁的情况下,
就能保证多个线程操作这个数据符合预期,确保数据的安全(或一致)性
那么,这个变量就是线程安全的。
1. 在Bean对象中尽量避免定义可变的成员变量(不太现实)。
2. 在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。
get():返回此线程局部变量当前副本中的值
set(T value):将线程局部变量当前副本中的值设置为指定值
initialValue():返回此线程局部变量当前副本中的初始值
remove():移除此线程局部变量当前副本中的值
ThreadLocalMap用键值对方式存储每个线程变量的副本,
key为当前的ThreadLocal对象,value为对应线程 的变量副本。
42-共享变量一定不安全吗?
不,如果前面加final,就是常量,常量只有一份,且不变,所以,就是安全的。
任何线程都动不了我,当然安全了。
比如我把数据放到公共区域的堆内存中,但是始终都只会有1个线程,
也就是单线程模型,那这数据肯定是安全 的。
再者说,2个线程操作同一个数据和200个线程操作同一个数据,
这个数据的安全概率是完全不一样的。肯定线程 越多数据不安全的概率越大,
线程越少数据不安全的概率越小。
取个极限情况,那就是只有1个线程,那不安全概 率就是0,也就是安全的。
70-线程安全
线程安全就是多线程访问时,
采用了加锁机制,
当一个线程访问该类的某个数据时,进行保护,
其他线程不能进行访问直 到该线程读取完,
其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,
有可能 出现多个线程先后更改数据造成所得到的数据是脏数据
一个线程想要执行synchronized修饰的方法里的代码,
首先是尝试获得 锁,如果拿到锁,执行synchronized代码体的内容,
如果拿不到锁的话,这个线程就会不断的尝试获得这把锁,直到拿到 为止,
而且多个线程同时去竞争这把锁,也就是会出现锁竞争的问题。
以上是关于什么是线程安全的主要内容,如果未能解决你的问题,请参考以下文章