Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查锁是否保持,但如果锁是自由的,则不锁定_Java_Multithreading_Reentrantlock - Fatal编程技术网

Java 检查锁是否保持,但如果锁是自由的,则不锁定

Java 检查锁是否保持,但如果锁是自由的,则不锁定,java,multithreading,reentrantlock,Java,Multithreading,Reentrantlock,我有一个场景,其中我有多个计数器对象。每个计数器对象可以由多个线程同时递增,因此所有对象都有一组ReentrantLock,这很好——每个对象在给定时刻只能由一个线程修改 这里有一个陷阱:有一个进程每15分钟运行一次,收集所有计数器对象,进行一些计算并清除计数器。此线程未锁定任何内容,因此存在以下情况: 递增线程正在获取计数器对象并递增某些计数器 clearing_线程正在获取所有计数器对象,执行一些计算并清除计数器 清除线程将计数器对象保存到缓存 递增线程将计数器对象保存到缓存 在这种情况下,

我有一个场景,其中我有多个计数器对象。每个计数器对象可以由多个线程同时递增,因此所有对象都有一组ReentrantLock,这很好——每个对象在给定时刻只能由一个线程修改

这里有一个陷阱:有一个进程每15分钟运行一次,收集所有计数器对象,进行一些计算并清除计数器。此线程未锁定任何内容,因此存在以下情况:

  • 递增线程正在获取计数器对象并递增某些计数器
  • clearing_线程正在获取所有计数器对象,执行一些计算并清除计数器
  • 清除线程将计数器对象保存到缓存
  • 递增线程将计数器对象保存到缓存
  • 在这种情况下,计数器对象中的一个被弄乱了,因为在最后清除操作被丢弃,并且计数器的状态与清除之前相同

    我想说的是:

    • 所有递增的线程都锁定在特定的计数器对象上,因此每个对象只能由一个线程修改,但同时独立的对象可以由多个线程修改,这项工作已经很好了
    • 当清除_线程开始时,它会设置某种标志,所有递增的_线程都会读取该标志,并且它们必须等待该标志被解除
    我有备份计划:

    • 清除所有对象上的线程锁,但我不喜欢这个想法,因为它可能需要太长时间,如果它阻塞其中一个对象,可能会阻塞所有线程
    • 我可以为每个对象清除for循环中的计数器,但在清除一个对象时,可以修改其他对象,这对我来说并不理想
    正如你所看到的,我有一些选择,但我想知道是否有更好的方法来做到这一点

    更新 我被要求提供代码,所以代码就在那里

    下面是在对象上增加计数器的方法之一的示例

    public void sipIncomingCall(String objName) {
        try {
            lock(objName);
            Stats stat = getStatisticsForObj(objName);
            long l = stat.getSipIncomingConnections().incrementAndGet();
            stat.getSipConnectionsSum().incrementAndGet();
            LOGGER.debug("incrementing sip incoming connections to {}, objName {}", l, objName);
            putStatisticsForObj(objName, stat);
        }finally {
            unlock(objName);
        }
    }
    
    lock()和unlock()方法:

    下面是“clearing_thread”的片段,它将所有统计对象复制到本地映射,然后清除集群中的统计信息:

        statisticsData.setObjStats(new HashMap<>(Cluster.getTgStatistics()));
        Cluster.clearTgStatistics();
    
    statisticsData.setObjStats(新的HashMap(Cluster.getTgStatistics());
    Cluster.clearTgStatistics();
    
    您可以使用
    ReadWriteLock

    • 递增线程在递增值之前获取读锁
    • 清理线程获取写锁

    每个计数器仍然需要单独的锁。

    您可以使用
    ReadWriteLock

    • 递增线程在递增值之前获取读锁
    • 清理线程获取写锁

    每个计数器仍然需要单独的锁。

    请添加代码。代码显示超过1000000个单词。我添加了代码,但同时问题被解决了:)请添加代码。代码显示了超过1000000个单词。我添加了代码,但同时问题被解决了:)
    private MgcfStats getStatisticsForObj(String tgName) {
        //get object from local cache (or hazelcast)
        return Cluster.getTgStatistics(tgName);
    }
    
    private void putStatisticsForObj(String tgName,MgcfStats stats){
        //saving to local cache and hazelcast
        Cluster.putTgStatistics(tgName,stats);
    }
    
        statisticsData.setObjStats(new HashMap<>(Cluster.getTgStatistics()));
        Cluster.clearTgStatistics();