使用多个线程从同一缓存中读取数据时获得不同的价值

时间:2019-08-12 08:23:52

标签: java infinispan infinispan-9

我正在尝试使用infinispan缓存实现计数器系统。多个线程正在尝试访问同一密钥,并根据该密钥递增值。

计数器操作以lock(key)开头,因此没有其他线程可以对其进行写操作。锁获取的线程执行get(key),递增该值,然后将其放回相同的密钥。

另一个正在等待锁释放的线程调用get(key)。 get(KEY)返回先前的值,而不是预期的更新后的计数器值。

我正在针对每个线程中的缓存开始新的事务。交易是自动提交的。

我尝试使用自动提交以及放置后显式提交。 我还确保每次运行前都要清除文件持久性和db持久性。

这是我的infinispan缓存配置。

<distributed-cache name="COUNTER_CACHE">
<transaction transaction-manager-lookup="com.suntecgroup.tbms.container.services.cluster.ContainerCacheTxManagerLookup" mode="FULL_XA" locking="PESSIMISTIC"/>
<state-transfer timeout="360000" await-initial-transfer="true" enabled="true"/>
<locking isolation="READ_COMMITTED" acquire-timeout="60000" concurrency-level="100" striping="false"/>
<memory>
<off-heap size="1000" eviction="COUNT"/>
 <!--  Determines the max entries to hold in the cache  -->
</memory>
<persistence passivation="false">
<file-store path="./infinispan_persistance_tmp/" max-entries="1000"/>
<store class="com.suntecgroup.tbms.container.cache.store.ispn.InfinispanCounterCacheStore" fetch-state="false" preload="true" shared="false" purge="false" read-only="false" singleton="false"> </store>
</persistence>
</distributed-cache>

预期结果是,当另一个线程尝试获得相同的值时,应该反映对线程所做的任何更新。

我最好的猜测是它必须对每个线程创建的事务做些事情。

我无法共享实际的代码,但是以下代码可以简化该过程。希望这会有所帮助

class CounterThread implements Runnable{

    public Integer getCounterVal(String key){
        int counter = cacheDelegate.get(key);
        if(counter==null){
                synchronized (Counter.class) {
                    if(counter = cacheDelegate.beginTransactionIfNoneAndGetObjectWithLock(key)){                
                    counter = 0;
                    cacheDelegate.putAndCommit(key,counter);
                    }
            }
        }   else
        counter = cacheDelegate.beginTransactionIfNoneAndGetObjectWithLock(key);
        return  counter;
    }

    public void putCounterVal(String key,int val){
        val++;
        cacheDelegate.putAndCommit(key,val);
    }

    public void run(){
        int i = 0;
        while(i<100){
            int counter = getCounterVal("KEY");
            putCounterVal("KEY",counter);
            i++;
        }
    }
}

// this method is used in beginTransactionIfNoneAndGetObjectWithLock to create a transaction
public void begin()
            throws ContainerPlatformServicesException {
        try {
            if (getCache("COUNTER_CACHE").getAdvancedCache().getTransactionManager()
                    .getTransaction() == null) {
                getCache("COUNTER_CACHE").getAdvancedCache().getTransactionManager()
                        .setTransactionTimeout(transactionTimeOut);
                getCache("COUNTER_CACHE").getAdvancedCache().getTransactionManager()
                        .begin();
            }
        }catch(TimeoutException e){
            logger.warn("TimeoutException exception caught. Required node is suspected. Thus waiting for suspect completion, to begin transaction.");
        } 
        catch (Exception e) {
            logger.error("Failed to begin transaction. Details:-", e);
        }
    }


// Only two threads are running.

0 个答案:

没有答案