【问题标题】:Restricting access to shared data with re-entrant lock in java在java中使用重入锁限制对共享数据的访问
【发布时间】:2016-02-07 13:39:01
【问题描述】:

我有一个简单的要求,其中一个资源(比如说一个链表)在两个服务之间共享:一个向它添加元素,另一个计算它的统计信息。我想在java中使用可重入锁。我想出了以下解决方案。

还有比这更好的解决方案吗?

public class SharedServer {
    private List<Integer> numbers;

    public SharedServer(List<Integer> numbers){
        this.numbers = numbers;
    }

    Lock lock = new ReentrantLock();

    public void addElements(int element){
        try{
            Thread.sleep(100);
            System.out.println("Adding element");
            numbers.add(element);
            System.out.println("Added : "+element);
        }catch(InterruptedException e){
            System.out.println("Interrupted while adding elements");
        }  
    }

    public void caluclateStatistics(){
        try{
            Thread.sleep(200);
            System.out.println("calculating statistics");
            System.out.println("Min : "+Collections.min(numbers)+" Max :      "+Collections.max(numbers)+" Avg : "+(Collections.min(numbers)+Collections.max(numbers))/numbers.size());
        }catch(InterruptedException e){
            System.out.println("Interrupted while performing calculations on elements");
        }
   }

}

public class StatisticsCalculator implements Runnable {

    private SharedServer sharedServer;

    public StatisticsCalculator(SharedServer sharedServer){
        this.sharedServer = sharedServer;
    }

    @Override
    public void run() {
        System.out.println("Calculator");
        boolean acquired = false;
        try {
            acquired = sharedServer.lock.tryLock(300,TimeUnit.MILLISECONDS);
            sharedServer.caluclateStatistics();
        } catch (InterruptedException e) {
            System.out.println("COULD NOT ACQUIRE CALCULATOR");
            e.printStackTrace();
        }finally{
            if(acquired){
                sharedServer.lock.unlock();
                System.out.println("Calculator released");
            }
        }

  }
}


public class ElementAdder implements Runnable {

    private SharedServer sharedServer;

    public ElementAdder(SharedServer sharedServer){
        this.sharedServer = sharedServer;
    }

    @Override
    public void run() {
        System.out.println("Adder");
        boolean acquired = false;
        try {
            acquired = sharedServer.lock.tryLock(300,TimeUnit.MILLISECONDS);
            sharedServer.addElements(ThreadLocalRandom.current().nextInt(1, 1000));
        } catch (InterruptedException e) {
            System.out.println("COULD NOT ACQUIRE ADDER");
            e.printStackTrace();
        }finally{
            if(acquired){
                sharedServer.lock.unlock();
                System.out.println("Adder released");
            }
        }
     }

}


public class Main {

    public static void main(String[] args) {
        List<Integer> ints = new ArrayList<>();
        SharedServer sharedService = new SharedServer(ints);
        ExecutorService executorService1 = Executors.newCachedThreadPool();
        ExecutorService executorService2 = Executors.newCachedThreadPool();
        for(int index=0; index<50;index++){
            executorService1.submit(new ElementAdder(sharedService));
        }
        for(int index=0; index<50;index++){
            executorService2.submit(new StatisticsCalculator(sharedService));
        }
        executorService1.shutdown();
        executorService2.shutdown();
    }

 }

唯一强制性的就是不调用(加法器或计算器)不应该错过。

【问题讨论】:

  • 这里真正需要配置什么:获取锁的超时时间,获取锁的方法(tryLock/lock)还是别的什么?如果这些都不是,那你为什么要暴露锁?
  • 我可以保持私有锁,并从 ElementAdder 和 StatisticsCalculator 中完全取消它。但是,我的问题是,这是正确的方法吗
  • 这取决于视角。如果它是一些真实产品的代码,可能会被其他开发人员访问,那么这种方法是不可行的:你的类的用户必须了解一些内部细节,这种方法很容易出错。如果它是一次性使用的代码,并且您永远不会再使用它,那么它可能是一个合理的解决方案。此外,您没有回答任何相关问题(“您真正需要在此处配置什么”部分)。

标签: java reentrantlock


【解决方案1】:

您是否有特定的理由使用可重入锁?你的calculateStatistics() 方法做 IO 吗? (不确定您的示例是否过于简单)

通常,synchronized 在概念上更简单,更容易正确处理,因此除非您需要超时(或 ReentrantLock 的其他功能),否则您可能需要考虑仅使用 synchronized。

【讨论】:

  • 我没有具体的理由使用重入锁。只是想试试java中的可重入锁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
  • 2013-05-29
  • 2010-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多