Titan ConcurrentModificationException

时间:2015-12-03 10:02:41

标签: java multithreading titan

我正在使用Titan-1.0.0测试批量加载

我在配置文件中设置 storage.batch-loading = true

我在我的java程序中使用TitanBlueprintsTransaction来表示图形加载性能,它是多线程的。

我在加载过程中遇到ConcurrentModificationException异常,我的代码就像这样

在线程#1中,使用titan复合索引搜索顶点,如此

Iterator<TitanVertex> it = tx.query().has("key", key).vertices().iterator();
TitanVertex vtx = it.next();

在线程#2中,尝试在同一顶点添加边

tx.getVertex(v).addEdge(edgeLabel, target);

当一个线程打开一个迭代器,另一个正在修改同一个顶点时,可能会发生异常。我该如何解决这个异常?

2 个答案:

答案 0 :(得分:0)

在以前的版本中,storage.batch-loading仅用于单线程操作。 http://thinkaurelius.github.io/titan/wikidoc/0.4.4/Graph-Configuration.html 在Titan 1.0中可能仍然如此。

答案 1 :(得分:0)

我对泰坦并不熟悉,但如果我遇到多线程问题,我会尝试分析哪里 并发访问发生了,我可以同步并发访问的最小区域是什么, 或者有哪些更好的替代方案(例如:线程安全的收集替代方案,其他访问方式)。

此代码模拟此错误:

public class ConcurrentMod
{

    public static <C extends Collection<String>> void fillCollectionTestData(C coll)
    {
        for(int i=0;i<10000;++i)
            coll.add(String.valueOf(i));
    }

    public static void main(String[] args)
    {
        final List<String> data = new ArrayList<>();
        fillCollectionTestData(data);

        new Thread()
        {
            public void run()
            {
                //heavy opertaion for an array
                for(int i=0;i<100;++i)
                    data.remove(i);
            }
        }.start();

        for(String s:data)
            s.length();
    }
}

常规列表(ArrayList,LinkedList)无法处理并发访问。 但是,正如我测试的那样,Vector的迭代器无法处理这种情况(WAT?很高兴知道)。 因此,如果您可以修改实现代码,则无法简单地将Collection类型更改为另一个并发安全类型。

另一个想法是:如果“tx.query()。有(”key“,key).vertices()”返回基于Collection的值你可以使用它的toArray(new Type [0]) 并通过它的副本进行迭代。在此示例中,将main中的迭代周期修改为:     for(String s:data.toArray(Mirror.emptyStringArray))         s.length();

解决问题,但是如果实现后面的Collection不管理并发访问,则可能仍然存在并发问题。 我的意思是:一个例子:一个类型声明它根本不包含空值,但是如果在一个线程中调用了一个删除而你在另一个调用了另一个(T) 你也许可以面对一个空值的数组!因为您看到了不完整的操作视图。删除已完成的一半但未恢复一致性,因为删除未完全完成。 如果你不能确定后面的实现处理这个,你需要使用外部同步:

    for(int i=0;i<100;++i)
        //other threads can access array between 2 heavy array shifting
        synchronized(data)
        {
            data.remove(i);
        }

    //and synchronize during array copy
    String[] tmp = null;
    synchronized(data)
    {
        tmp = data.toArray(Mirror.emptyStringArray);
    }

    for(String s:tmp)
        s.length();