Java笔试题(三)——线程安全、String、StringBuffer、StringBuilder

1.什么是线程安全?

简单地说法:线程安全可以简单理解为一个方法或者一个实例可以在多线程环境中使用而不会出现问题。

复杂的说法:当多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替运行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获取正确的结果,那这个对象是线程安全的。

2.保证线程有什么方法?

一般说来,确保线程安全的方法有这几个:竞争与原子操作、同步与锁、可重入、过度优化

竞争与原子操作 
多个线程同时访问和修改一个数据,可能造成很严重的后果。出现严重后果的原因是很多操作被操作系统编译为汇编代码之后不止一条指令,因此在执行的时候可能执行了一半就被调度系统打断了而去执行别的代码了。一般将单指令的操作称为原子的(Atomic),因为不管怎样,单条指令的执行不会被打断的。

因此,为了避免出现多线程操作数据的出现异常,Linux 系统提供了一些常用操作的原子指令,确保了线程的安全。但是,它们只适用于比较简单的场合,在复杂的情况下就要选用其他的方法了。

同步与锁 
为了避免多个线程同时读写一个数据而产生不可预料的后果,开发人员要将各个线程对同一个数据的访问同步,也就是说,在一个线程访问数据未结束的时候,其他线程不得对同一个数据进行访问。

同步的最常用的方法是使用锁(Lock),它是一种非强制机制,每个线程在访问数据或资源之前首先试图获取锁,并在访问结束之后释放锁;在锁已经被占用的时候试图获取锁时,线程会等待,直到锁重新可用。

二元信号量是最简单的一种锁,它只有两种状态:占用与非占用,它适合只能被唯一一个线程独占访问的资源。对于允许多个线程并发访问的资源,要使用多元信号量(简称信号量)。

可重入 
一个函数被重入,表示这个函数没有执行完成,但由于外部因素或内部因素,又一次进入该函数执行。一个函数称为可重入的,表明该函数被重入之后不会产生任何不良后果。可重入是并发安全的强力保障,一个可重入的函数可以在多线程环境下放心使用。

阻止过度优化 
在很多情况下,即使我们合理地使用了锁,也不一定能够保证线程安全,因此,我们可能阻止对代码进行过度的优化以确保线程安全。

我们可以使用 volatile 关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,阻止编译器调整操作 volatile 变量的指令顺序。

在另一种情况下,CPU 的乱序执行让多线程安全保障的努力变得很困难,通常的解决办法是调用 CPU 提供的一条常被称作 barrier 的指令,它会阻止 CPU 将该指令之前的指令交换到 barrier 之后,反之亦然。

3.String 是不是线程安全?为什么?

String 是线程安全的。主要原因是 String 内部存储字符串的 char 数组以及和 char 数组相关的信息都是 final 的,这就保证了String 对象生成的那一刻他在内存里就是不可变的。

String:String 类代表字符串。

StringBuffer:线程安全的可变字符序列。线程安全

StringBuilder:一个可变的字符序列。非线程安全

三者的区别

1.String 类型的字符串对象是不可变的,一旦 String 对象创建后,包含在这个对象中的字符系列是不可以改变的,直到这个对象被销毁。

2.StringBuilder 和 StringBuffer 类型的字符串是可变的。

3.StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是 StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的。

4.如果是多线程环境下涉及到共享变量的插入删除操作,StringBuffer 则是首选。如果是非多线程操作并且有大量的字符串拼接,插入,删除操作则 StringBuilder 是首选。毕竟 String 类是通过创建临时变量来实现字符串拼接的,耗内存还效率不高,StringBuilder 是通过 JNI 方式实现终极操作的。

5.StringBuilder 和StringBuffer 的“可变”特性总结如下:
         (1)append,insert,delete 方法最根本上都是调用 System.arraycopy() 这个方法来达到目的
         (2)substring(int, int) 方法是通过重新 new String(value, start, end - start) 的方式来达到目的。因此,在执行 substring 操作时,StringBuilder 和 String 基本上没什么区别。

6.三者在执行速度方面的比较:StringBuilder > StringBuffer > String。

猜你喜欢

转载自blog.csdn.net/qq_36847713/article/details/83512482