• 可重入(线程安全)


    可重入(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;
    	}
    }
    

      

  • 相关阅读:
    guava学习--集合2&Range
    guava学习--集合1
    guava学习--FluentIterable
    guava学习--Supplier Suppliers
    guava--Joiner、Splitter、MapJoinner、MapSplitter
    python_输入一个数,判断是否是素数
    python_33_文件操作2
    python_32_文件操作1
    python_31_集合
    python_输出100:200内的素数
  • 原文地址:https://www.cnblogs.com/mengxinrenyu/p/8097865.html
Copyright © 2020-2023  润新知