什么是线程安全?

线程double

“线程安全” 不是指线程的安全,而是指内存的安全,这和操作系统有关系。

目前主流操作系统都是多任务的,即多个进程同事运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程,这是由操作系统保障的。

在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的所有线程都可以访问区域,这就是造成问题的潜在原因。

跟js使用闭包是一个道理

假设某个线程把数据处理到一半,觉得很累,就去休息了一会,回来准备接着处理,却发现数据已经被修改了,不是自己离开时的样子。可能被其他线程修改了。所以线程安全指的是,在堆内存中的数据由于可以被如何线程访问到,在没有限制的情况下存在被意外修改的风险。

即堆内存空间在没有保护机制的情况下,对多线程来说是不安全的地方,因为你放进去的数据,可能被别的线程 “破坏”。

那我们应该怎么办?解决问题的过程其实就是一个取舍的过程,不同解决方案有不同的侧重点。

私有的东西就不应该让别人知道

现实中很多人都会把钱藏着掖着,不然那无关的人知道,所以根本不可能扔到大马路上,因为这钱是你的私有物品。在程序中也是这样的,所以操作系统会为每个线程分配属于它自己的内存空间,通常称为栈内存,其他线程无权访问。这也是由操作系统保障的。

如果一些数据只有某个线程会使用,其他线程不能操作也不需要操作,这些数据就可以放入线程的栈内存中,较为常见的就是局部变量。

class MyRunnable implements Runnable { @Override public void run() { int i = 0; while (i < 10) { i++; System.out.println("线程" + Thread.currentThread().getName() + ":" + i); } } } public class Test { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.run(); Thread thread1 = new Thread(myRunnable); thread1.run(); } }

这里的变量 i 是局部变量,它们都会被分配在线程栈内存中。

假如现在A线程来执行这个方法,这些变量会在A的栈内存分配,与此同时,B线程也来执行这个方法,这些变量也会在B的栈内存中分配。

也就是说这些局部变量会在每个线程的栈内存中都分配一份,由于线程的栈内存只能自己访问,所以栈内存中的变量只属于自己,其他线程根本就不知道。

就像每个人的家只属于自己,其他人不能进来。所以你把钱放到家里,其他人事不会知道的,且一般还会放到某个房间里,而不是扔在客厅的桌子上。所以把自己的东西放到自己的私人底盘是安全的,因为其他人无法知道,而且越隐私的地方越好。

扩展阅读