线程和进程最大的根本区别就是内存数据的共享。
每个进程都独享一个虚拟内存[虚拟内存 = 物理内存 + SWAP/页面文件)]。
一个进程可以拥有多个线程,一般来说一个线程仅独享一个进程的虚拟内存中的一个函数栈帧。
程序储存数据有下面几种常用的方式:
自动变量: 自动变量是储存在栈中的,随着函数的调用而产生,结束而销毁。
静态(全局)变量: 静态分配的变量是随着程序的运行产生,程序的结束而销毁,这些变量储存在内存一个专门存放静态变量的区域。
堆: 即通过malloc()申请的内存,一旦申请后,直到调用free(),或程序结束后才释放。
其中造成“非线程安全”的主要是静态变量以及堆。
自动变量仅存在于函数自己的栈中,不管你如何修改其值,均不会影响其他函数(准确来说是线程)的数据。
静态变量独立储存于一个区域,这就意味着一个静态变量由整个进程的所有线程共享,一个线程修改了静态变量的值,将会改变其他线程读对该变量取得的结果,储存于堆的数据亦如此。
所谓“线程安全”,即采取了的措施,避免不同的线程同时对一个变量进行修改。
例如某些函数的结果保存于静态分配的变量,或者是保存于堆中的一个区域,可以选择通过加锁,或互斥量来阻塞其他线程对这些函数的调用,但细心的话你也看到了“阻塞”二字,因此最佳的办法就是避免采用这些用到静态分配或堆的函数。
如果你用过PHP的Pthreads模块,并且理解了本文,那你应该明白为何Pthreads模块强制要求使用线程安全版本的PHP。