可重入(线程安全)
可重入(reentrant)的类或方法,又称线程安全(threadsafe)的类或方法。
是指一个类或方法,在多个线程里同时调用(并发调用)的时候,其功能仍然正常。
如在并发调用时功能出错的方法(线程不安全的Thread Unsafe)
例如,下面的方法用于求和
int sum(int n){
int result=0;
for(int i=1;i<=n;i++){
result+=i;
}
return result;
}
我们的代码:
class Add{
static int sum(int n){
int result=0;
for(int i=1;i<=n;i++){
result+=i;
}
return result;
}
}
public class Demo {
public static void main(String[] args) {
new Thread(new Runnable(){
@Override
public void run(){
int n=500;
while(n--!=0){
int ret=Add.sum(100);
if(ret!=5050){System.out.println(Thread.currentThread().getName()+" "+ret);}
}
}
},"t1").start();
new Thread(new Runnable(){
@Override
public void run(){
int n=500;
while(n--!=0){
int ret=Add.sum(100);
if(ret!=5050){System.out.println(Thread.currentThread().getName()+" "+ret);}
}
}
},"t2").start();
}
}
运行时,方法sum始终能进行对1~100的求和,得出5050。所以是线程安全的。
我们从反面验证线程不安全的
将以上代码修改:
class Number{public static int result;}
class Add{
static int sum(int n){ //借助全局变量,此方法在单线程时是没有任何问题的(可运行测试)
Number.result=0;
for(int i=1;i<=n;i++){
Number.result+=i;
}
return Number.result;
}
}
public class Demo {
public static void main(String[] args) {
new Thread(new Runnable(){
@Override
public void run(){
int n=500;
while(n--!=0){
int ret=Add.sum(100);
if(ret!=5050){System.out.println(Thread.currentThread().getName()+" "+ret);}
}
}
},"t1").start();
new Thread(new Runnable(){
@Override
public void run(){
int n=500;
while(n--!=0){
int ret=Add.sum(100);
if(ret!=5050){System.out.println(Thread.currentThread().getName()+" "+ret);}
}
}
},"t2").start();
}
}
当计算结果不是5050时我们打印输出
运行如图:

可重入的方法
判断一个方法是否是可重入的:
(1)在单线程的情况下,该方法表现正常
如果单线程也不行,说明这个方法写错了
(2) 在多线程并发调用此方法时,该方法仍然表现正常。
则称为该方法是可重入的。
以下方法很可能是不可重入的:
(1)一个全局方法(写在类体之外的方法)
如果它借助于全局对象来实现,并且有写操作,那么就是不可重入的。
(2) 一个类的成员方法
它访问并修改了成员变量,那么一般情况下它就是不可重入的。
如何将不可重入的方法,改为可重入的?
(1) 不借助外部的变量来实现
尽量用本方法内定义的局部变量来实现。
或者在本方法动态创建对象
(没有外部依赖,不操作外部变量)
(2) 实在不行的话,加上互斥锁控制
class Number{public static int result;}
class Add{
static synchronized int sum(int n){ //synchronized将不可重入修改为可重入(加锁)
Number.result=0;
for(int i=1;i<=n;i++){
Number.result+=i;
}
return Number.result;
}
}
浙公网安备 33010602011771号