尝试在runnable中同步方法 [英] Trying to synchronize method within runnable

查看:134
本文介绍了尝试在runnable中同步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ConcurrentMap,它在我的runnables之外被实例化,但是在runnables中共享和更新。我的runnables需要是并发的,但我的concurrentMap更新需要同步以防止替换先前的entrys。有人能告诉我我做错了什么。

I have a ConcurrentMap that gets instantiated outside of my runnables, but shared and updated within / accross the runnables. My runnables need to be concurrent, but my concurrentMap update needs to be synchronized to prevent the replacement of previous entrys. Could someone tell me what I'm doing wrong.

public class ExecutionSubmitExample {

    public static void main(String[] args) {
        //Ten concurrent threads
        ExecutorService es = Executors.newFixedThreadPool(10);

        List<Future<Example>> tasks = new ArrayList<>();

        ConcurrentHashMap<Integer, String> concurrentMap = new ConcurrentHashMap<>();

        for (int x = 0; x < 10; x++) {
            Example example = new Example(concurrentMap, x);
            Future<Example> future = es.submit(example, example);
            tasks.add(future);
        }

        try {
            for (Future<Example> future : tasks) {
                Example e = future.get();
            }

            for (Entry<Integer,String> obj : concurrentMap.entrySet()) {
                System.out.println("key " + obj.getKey() + " " + obj.getValue());
            }
            es.shutdown();
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException ie) {
            throw new RuntimeException(ie);
        }
    }
}

Runnable

public class Example implements Runnable {

    ConcurrentHashMap<Integer, String> concurrentMap;
    private int thread;

    public Example(ConcurrentHashMap<Integer, String> concurrentMap, int thread) {
        this.concurrentMap = concurrentMap;
        this.thread = thread;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            runAnalysis(i);
        }
    }

    public synchronized void runAnalysis(int index) {
        if(concurrentMap.containsKey(index)) {
            System.out.println("contains integer " + index);
        } else {
            System.out.println("put " + index + " thread " + thread);
            concurrentMap.put(index, "thread " + thread);
        }
    }
}

结果 - 通知索引0被添加多次而不是一次。它应该由线程0添加并读取为线程9包含的内容。我不知何故需要从其他线程锁定此方法,直到更新完成。

Results - notice index 0 is added multiple times rather than once. It should be added by thread 0 and read as contained by thread 9. I somehow need to lock this method from the other threads until the update has been completed.

put 0 thread 0
put 0 thread 9
put 0 thread 6
put 0 thread 7
put 1 thread 7
put 0 thread 2
put 0 thread 1
put 0 thread 5
put 0 thread 3
put 0 thread 4
contains integer 1
contains integer 1
contains integer 1
contains integer 1
put 2 thread 7
put 1 thread 6
put 1 thread 9
put 1 thread 0
put 0 thread 8
contains integer 2
contains integer 2
contains integer 2
put 2 thread 2
put 2 thread 1
put 2 thread 5
put 2 thread 3
contains integer 1
contains integer 1
contains integer 2
contains integer 2
key 0 thread 8
key 2 thread 3
key 1 thread 0


推荐答案

synchronized 意味着在 synchronized >这个对象。由于每次都在创建新对象

synchronized on the method means synchronized on this object. Since you are creating new objects every time

Example example = new Example(concurrentMap, x);

同步发生在不同的对象上,因此没有任何阻止。

The synchronization is happening on different objects, so nothing blocks.

您需要在共享对象上 synchronized 或使用共享 Lock 。这些可以传递给示例对象,或者您可以使用 static 字段由Luiggi建议。在这种情况下,请注意该字段在其他任何地方都不同步或者它可能会干扰此次执行。

You need to synchronized on a shared object or use a shared Lock. These can be passed to the Example object or you can use a static field as suggested by Luiggi. In this case, be careful that the field isn't synchronized on anywhere else or it may interfere with this execution.

这篇关于尝试在runnable中同步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆