线程安全和线程不安全如何理解(php线程安全和不安全的区别)

本文目录
- php线程安全和不安全的区别
- python中的线程安全和非线程安全的区别
- Java线程安全和非线程安全
- 进程与线程的区别,线程安全”怎么理解
- 怎么理解Stringbuffer 是线程安全的 stringbuilder是线程不安全的
- 线程安全之不安全例子
- java里,数组,线程安全的和不安全的,是什么意思
php线程安全和不安全的区别
Windows下的PHP版本分两种:线程安全版本与非线程安全版本。
要论两者的区别,详细论说起来比较麻烦,从使用者的角度,记住什么时候用哪种版本的区别就可以了吧:
1、windows + IIS + FastCGI :使用非线程安全版本。
解释:
以FastCGI方式安装PHP时,PHP拥有独立的进程,并且FastCGI是单一线程的,不存在多个线程之间可能引发的相互干扰(这种干扰通常都是由于全局变量和静态变量导致的)。由于省去了线程安全的检查,因此使用FastCGI方式比ISAPI方式的效率更高一些。
2、windows + IIS + ISAPI :使用线程安全版本。
解释:
PHP以ISAPI方式安装时,PHP没有独立的进程,而是作为DLL被IIS加载运行的,即是依附于Web服务器进程的。当Web服务器运行在多线程模式下(IIS正是这种情况),PHP自然也就运行在多线程模式下。只要是在多线程模式下运行,就可能存在线程安全问题,因此应选择PHP的线程安全版本。
3、windows + Apache + PHP(模块) :使用线程安全版本。
解释:
如果你要在Apache中以模块方式安装PHP,则你应该使用PHP的线程安全的版本。原因是当PHP作为Apache的模块安装时,PHP没有独立的进程,而是作为模块以DLL的形式被加载到Apache中的,是随Apache的启动而启动的,而Windows下的Apache为多线程工作模式,因此PHP自然也就运行在多线程模式下。因此,这种情况下应使用PHP的线程安全版本。
4、windows + Apache + PHP(ISAPI) :使用线程安全版本。
解释:
由于以ISAPI方式来安装PHP时,PHP也没有独立的进程,也是作为模块被加载到Apache中的,因此,同样也需要使用PHP的线程安全版本。
一般不建议在Apache中以ISAPI方式来安装PHP,原因是到目前为止,Apache通过mod_isapi.so模块来实现的ISAPI功能并不完整,并未完整实现微软对ISAPI所制定的全部规范。
5、windows + Apache + PHP(FastCGI) :使用非线程安全版本。
解释:
如果你要在Apache中以FastCGI方式使用PHP,则同在IIS中使用FastCGI的PHP的情况一样,你应该使用PHP的非线程安全的版本。原因是在Apache中以FastCGI方式安装PHP时,PHP拥有独立的进程,并且FastCGI是单一线程的,故应使用PHP的非线程安全版本以提高性能
python中的线程安全和非线程安全的区别
线程安全和非线程安全这些概念在其他的编程语言也同样使用。
所谓线程安全:就是对于多线程同时操作是是安全的而不会发生写冲突,比如python的Queue
相反非线程安全:就是多线成同时操作时会发生写冲突,比如python的其他list,set,dict
Java线程安全和非线程安全
ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?StringBuilder和StringBuffer有什么区别?这些都是Java面试中常见的基础问题 面对这样的问题 回答是 ArrayList是非线程安全的 Vector是线程安全的 HashMap是非线程安全的 HashTable是线程安全的 StringBuilder是非线程安全的 StringBuffer是线程安全的 因为这是昨晚刚背的《Java面试题大全》上面写的 此时如果继续问 什么是线程安全?线程安全和非线程安全有什么区别?分别在什么情况下使用?这样一连串的问题 一口老血就喷出来了…
非线程安全的现象模拟
这里就使用ArrayList和Vector二者来说明
下面的代码 在主线程中new了一个非线程安全的ArrayList 然后开 个线程分别向这个ArrayList里面添加元素 每个线程添加 个元素 等所有线程执行完成后 这个ArrayList的size应该是多少?应该是 个?
public class Main
{
public static void main(String args)
{
// 进行 次测试
for(int i = ; i 《 ; i++)
{
test();
}
}
public static void test()
{
// 用来测试的List
List《Object》 list = new ArrayList《Object》();
// 线程数量( )
int threadCount = ;
// 用来让主线程等待threadCount个子线程执行完毕
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
// 启动threadCount个子线程
for(int i = ; i 《 threadCount; i++)
{
Thread thread = new Thread(new MyThread(list countDownLatch));
thread start();
}
try
{
// 主线程等待所有子线程执行完成 再向下执行
countDownLatch await();
}
catch (InterruptedException e)
{
e printStackTrace();
}
// List的size
System out println(list size());
}
}
class MyThread implements Runnable
{
private List《Object》 list;
private CountDownLatch countDownLatch;
public MyThread(List《Object》 list CountDownLatch countDownLatch)
{
this list = list;
untDownLatch = countDownLatch;
}
public void run()
{
// 每个线程向List中添加 个元素
for(int i = ; i 《 ; i++)
{
list add(new Object());
}
// 完成一个子线程
untDown();
}
}
public class Main
{
public static void main(String args)
{
// 进行 次测试
for(int i = ; i 《 ; i++)
{
test();
}
}
public static void test()
{
// 用来测试的List
List《Object》 list = new ArrayList《Object》();
// 线程数量( )
int threadCount = ;
// 用来让主线程等待threadCount个子线程执行完毕
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
// 启动threadCount个子线程
for(int i = ; i 《 threadCount; i++)
{
Thread thread = new Thread(new MyThread(list countDownLatch));
thread start();
}
try
{
// 主线程等待所有子线程执行完成 再向下执行
countDownLatch await();
}
catch (InterruptedException e)
{
e printStackTrace();
}
// List的size
System out println(list size());
}
}
class MyThread implements Runnable
{
private List《Object》 list;
private CountDownLatch countDownLatch;
public MyThread(List《Object》 list CountDownLatch countDownLatch)
{
this list = list;
untDownLatch = countDownLatch;
}
public void run()
{
// 每个线程向List中添加 个元素
for(int i = ; i 《 ; i++)
{
list add(new Object());
}
// 完成一个子线程
untDown();
}
}
上面进行了 次测试(为什么要测试 次?因为非线程安全并不是每次都会导致问题)
输出结果
上面的输出结果发现 并不是每次测试结果都是 有好几次测试最后ArrayList的size小于 甚至时不时会抛出个IndexOutOfBoundsException异常 (如果没有这个现象可以多试几次)
这就是非线程安全带来的问题了 上面的代码如果用于生产环境 就会有隐患就会有BUG了
再用线程安全的Vector来进行测试 上面代码改变一处 test()方法中
List《Object》 list = new ArrayList《Object》();
List《Object》 list = new ArrayList《Object》();改成
List《Object》 list = new Vector《Object》();
List《Object》 list = new Vector《Object》();
再运行程序
输出结果
再多跑几次 发现都是 没有任何问题 因为Vector是线程安全的 在多线程操作同一个Vector对象时 不会有任何问题
再换成LinkedList试试 同样还会出现ArrayList类似的问题 因为LinkedList也是非线程安全的
二者如何取舍
非线程安全是指多线程操作同一个对象可能会出现问题 而线程安全则是多线程操作同一个对象不会有问题
线程安全必须要使用很多synchronized关键字来同步控制 所以必然会导致性能的降低
所以在使用的时候 如果是多个线程操作同一个对象 那么使用线程安全的Vector 否则 就使用效率更高的ArrayList
非线程安全!=不安全
有人在使用过程中有一个不正确的观点 我的程序是多线程的 不能使用ArrayList要使用Vector 这样才安全
非线程安全并不是多线程环境下就不能使用 注意我上面有说到 多线程操作同一个对象 注意是同一个对象 比如最上面那个模拟 就是在主线程中new的一个ArrayList然后多个线程操作同一个ArrayList对象
如果是每个线程中new一个ArrayList 而这个ArrayList只在这一个线程中使用 那么肯定是没问题的
线程安全的实现
线程安全是通过线程同步控制来实现的 也就是synchronized关键字
在这里 我用代码分别实现了一个非线程安全的计数器和线程安全的计数器Counter 并对他们分别进行了多线程测试
非线程安全的计数器
public class Main
{
public static void main(String args)
{
// 进行 次测试
for(int i = ; i 《 ; i++)
{
test();
}
}
public static void test()
{
// 计数器
Counter counter = new Counter();
// 线程数量( )
int threadCount = ;
// 用来让主线程等待threadCount个子线程执行完毕
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
// 启动threadCount个子线程
for(int i = ; i 《 threadCount; i++)
{
Thread thread = new Thread(new MyThread(counter countDownLatch));
thread start();
}
try
{
// 主线程等待所有子线程执行完成 再向下执行
countDownLatch await();
}
catch (InterruptedException e)
{
e printStackTrace();
}
// 计数器的值
System out println(counter getCount());
}
}
class MyThread implements Runnable
{
private Counter counter;
private CountDownLatch countDownLatch;
public MyThread(Counter counter CountDownLatch countDownLatch)
{
unter = counter;
untDownLatch = countDownLatch;
}
public void run()
{
// 每个线程向Counter中进行 次累加
for(int i = ; i 《 ; i++)
{
counter addCount();
}
// 完成一个子线程
untDown();
}
}
class Counter
{
private int count = ;
public int getCount()
{
return count;
}
public void addCount()
{
count++;
}
}
public class Main
{
public static void main(String args)
{
// 进行 次测试
for(int i = ; i 《 ; i++)
{
test();
}
}
public static void test()
{
// 计数器
Counter counter = new Counter();
// 线程数量( )
int threadCount = ;
// 用来让主线程等待threadCount个子线程执行完毕
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
// 启动threadCount个子线程
for(int i = ; i 《 threadCount; i++)
{
Thread thread = new Thread(new MyThread(counter countDownLatch));
thread start();
}
try
{
// 主线程等待所有子线程执行完成 再向下执行
countDownLatch await();
}
catch (InterruptedException e)
{
e printStackTrace();
}
// 计数器的值
System out println(counter getCount());
}
}
class MyThread implements Runnable
{
private Counter counter;
private CountDownLatch countDownLatch;
public MyThread(Counter counter CountDownLatch countDownLatch)
{
unter = counter;
untDownLatch = countDownLatch;
}
public void run()
{
// 每个线程向Counter中进行 次累加
for(int i = ; i 《 ; i++)
{
counter addCount();
}
// 完成一个子线程
untDown();
}
}
class Counter
{
private int count = ;
public int getCount()
{
return count;
}
public void addCount()
{
count++;
}
}
上面的测试代码中 开启 个线程 每个线程对计数器进行 次累加 最终输出结果应该是
但是上面代码中的Counter未进行同步控制 所以非线程安全
输出结果
稍加修改 把Counter改成线程安全的计数器
class Counter
{
private int count = ;
public int getCount()
{
return count;
}
public synchronized void addCount()
{
count++;
}
}
class Counter
{
private int count = ;
public int getCount()
{
return count;
}
public synchronized void addCount()
{
count++;
}
}
上面只是在addCount()方法中加上了synchronized同步控制 就成为一个线程安全的计数器了 再执行程序
输出结果
lishixinzhi/Article/program/Java/gj/201311/27519进程与线程的区别,线程安全”怎么理解
一个程序就是一个进程,而一个程序中的多个任务则被称为线程。进程是表示资源分配的基本单位,又是调度运行的基本单位。线程是进程中执行运算的最小单位,亦即执行处理机调度的基本单位。 进程和线程的关系
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。
(3)处理机分给线程,即真正在处理机上运行的是线程。
(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
如果把上课的过程比作进程,那么每个学生就是一个线程,他们共享教室,即线程共享进程的内存空间。每一个时刻,只能一个学生问老师问题,老师回答完毕,轮到下一个。即线程在一个时间片内占有cpu。
怎么理解Stringbuffer 是线程安全的 stringbuilder是线程不安全的
线程安全,主要是指多线程操作同一个数据时,防止脏数据的产生。主要的应用场景是应用缓存,缓存是整个系统公用的数据,在多线程系统中,线程的异步访问和修改会导致数据产生异常。
考虑一个场景,A和B两个线程同时操作缓存中的一条数据,A线程对数据进行自加处理,B线程对数据进行校验,如果校验不过,就清除数据。
非线程安全的情况:当A获取到这条数据,准备修改时,B线程进来了,校验完数据,发现数据不正确,就把数据移除了,这时A线程仍旧认为当前持有的数据还是开始获取的数据,这样再做处理就会报空。
线程安全的情况:就是当一个线程需要对这个数据进行改写时,会给这个数据上一个同步锁,比如A线程拿到数据后,给数据加上同步锁,这时候B线程进来了,但是这时候数据已经上锁,B线程则需要等待A线程释放锁之后才能对数据进行操作,这样就防止了脏数据的产生。
Java API的Stringbuffer 和 HashTable是在较低版本的JDK中提供的。随着软件项目越来越负责,系统对于性能要求越来越高,然而线程的同步访问对系统性能有很大的影响,所以才会有效率更高的StringBuilder和HashMap的产生。当然在使用这些非线程安全的集合时,线程安全问题就需要开发人员自己控制。
StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。
StringBuffer buf=new StringBuffer(); //分配长16字节的字符缓冲区
StringBuffer buf=new StringBuffer(512); //分配长512字节的字符缓冲区
StringBuffer buf=new StringBuffer("this is a test")//在缓冲区中存放了字符串,并在后面预留了16字节的空缓冲区。StringBuffer
StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类。线程安全
StringBuffer 线程安全
StringBuilder 线程不安全速度
一般情况下,速度从快到慢:StringBuilder》StringBuffer》String,这种比较是相对的,不是绝对的。总结
(1).如果要操作少量的数据用 = String
(2).单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
(3).多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
线程安全之不安全例子
当你用public static声明这个类型的具体实例(对于class来说其实例就是对象)时是线程安全的。其他时候创建的实例就不能保证线程安全。
举例说,如果一个类里包含若干个成员,有的是public static成员,有的不是。那么只有那些poublic static的成员能够保证多个线程访问时,其成员的值(对于引用可以理解为引用对象的指针)是线程安全的。至于这些成员下面的成员是否线程安全则还要看这个类型自己的设计如何。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了,呵呵。
java里,数组,线程安全的和不安全的,是什么意思
比如说,两个线程操作同一个ArrayList变量,那么一个线程这一时刻读的数据可能在下一刻要改变。
一般在类似于下面的情景下考虑线程安全的问题:
ArrayList products=new ArrayList ();
products用来存放生产出来的产品。
现在假设:有3个消费者线程,2个生产者线程。
每个生产者线程生产出一个产品,执行
products.add(new Product());
每个消费者线程消费一个产品执行
if(products.size()》=1){ products.remove(0);}
如果products里现在只有一个产品可以消费,但是有2个消费者线程请求消费,那么就有可能出现一个产品被同时消费的问题,而这是和实际不符的。
但是不同的线程访问Vector的时候不会发生这种错误,因为java会有相应的机制是同一时刻只有一个线程对这个变量操作。
这就是所谓的:
Vector:是线程安全的
ArrayList:不是线程安全的

更多文章:
directive vue(如何在Vue中建立全局引用或者全局命令)
2026年5月6日 19:15
javaeclipse包的新建(用eclipse如何创建java工程)
2026年1月11日 08:30
c语言switch语句case后面接什么(c语言switch语句中case后面必须要接整型常量和字符型常量吗)
2025年10月26日 08:15
怎么把普通文件导入变成web项目(java项目怎么转成web项目)
2025年9月18日 16:00
在循环体内使用break语句(在循环结构中使用break语句,退出的是一层循环,还是多重循环呢可以给出一个简单且巧妙的例子吗)
2026年5月1日 00:00
position在css的属性(CSS中position属性详解)
2025年9月26日 23:45
amazed是什么牌子(amazing和amazed有什么区别)
2026年4月3日 15:00
周期函数值域的求法(已知函数的最小正周期为求;当时,求函数的值域.)
2025年11月30日 22:15
毕设做网站必须要用到ssm框架嘛(毕业设计做ssm还是app更难)
2026年3月31日 03:00
new directory(如何将威纶通tk6070ip触摸屏程序上传到电脑里)
2026年8月7日 01:45













