360笔试题:多线程的变量访问
有这样一道360笔试题:
以下说法不正确的是( )。
A.在多线程中不加限制的随意访问非static局部变量可能会导致运算结果出错
B.在多线程中不加限制的随意访问非static全局变量可能会导致运算结果出错
C.在多线程中不加限制的随意访问static局部变量可能会导致运算结果出错
D.在多线程中不加限制的随意访问static全局变量可能会导致运算结果出错
本题考查的知识点是多线程的变量访问。
程序 语言 提供的这些种类的变量为程序设计提供了精准的数据描述手段。
按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
一组并发线程运行在一个进程的上下文中,每个线程都有它自己独立的线程上下文。例如:栈、程序计数器、线程ID、条件码等。每个线程和其他的线程一起共享除此之外的进程上下文的剩余部分,包括整个用户的虚拟地址空间,如文件、全局变量、静态数据、堆内存、同步锁变量、组件对象等。
每次调用函数时,编译程序将非static局部变量放入线程的执行栈中,退出函数时,非static局部变量从栈中舍弃。由于每个线程都有专用的运行栈,所以多个线程即使访问同一个函数中的同一个非static局部变量,实际上访问的也是不同的内存单元。因此,线程在使用非static局部变量时不会与其他线程发生同时访问一个变量的情况。
非静态局部变量存在于线程自己独立的空间内,对它的访问可以是随意的,或者说,一个线程内对某非静态局部变量的访问不会影响到另一个线程中该变量的值。故选项 A 是不正确的。
题中其他三种类型的变量,编译时都分配到了程序运行空间的数据区,被进程中的所有线程所共享,可能发生多个线程同时访问一个数据的情况。
有了共享就要防止在对共享变量进行操作的过程中得到一个不可知的值。使用这些公共资源的线程必须同步。
多线程的环境下,线程的执行顺序是不可知的,线程中对变量的访问次序就可能与预想的不一致。并发线程访问一个数据时,可以同时读,但不能同时读和写,也不能同时写,否则会出现错误。即并发线程不加限制的随意访问一个数据,会出错。
总之,要确保函数线程安全,必须考虑线程之间的共享变量。属于同一进程的不同线程会共享进程内存空间中的全局区和堆,而私有的线程空间则主要包括栈和寄存器。因此,对于同一进程的不同线程来说,每个线程的局部变量都是私有的,而全局变量、局部静态变量、分配于堆的变量都是共享的。在对这些共享变量进行访问时,不能随意,必须通过加锁的方式。
本文已收录于《横扫Offer--程序员招聘真题详解700题》一书,开点工作室著,清华大学出版社,该书目前已编写修改完成,7月即将上市。更多程序员笔试面试真题的精彩详解请参见该书。