Trying to synchronize method within runnable

后端 未结 4 1211
清歌不尽
清歌不尽 2020-12-21 22:45

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 conc

相关标签:
4条回答
  • 2020-12-21 23:23

    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.

    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.

    0 讨论(0)
  • 2020-12-21 23:26

    You should avoid synchronizing when using a ConcurrentMap. It provides other methods for handling these types of operations. For this case the putIfAbsent method should be preferred over a contains and then a put.

    public void runAnalysis(int index) {
        if (concurrentMap.putIfAbsent(index, "thread " + thread) == null) {
            System.out.println("put " + index + " thread " + thread);
        } else {
            System.out.println("contains integer " + index);
        }
    }
    
    0 讨论(0)
  • 2020-12-21 23:39

    Solution based on Sotirios Delimanolis, Luiggi Mendoza, Sotirios Delimanolis answer.

    main

    public class ExecutionSubmitExample {
    
        public static void main(String[] args) {
            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 e = new Example(concurrentMap, x);
                Future<Example> future = es.submit(e, e);
                tasks.add(future);
            }
            // -- all threads should be launching, let's get the ExecutionSubmitExample objects
    
    
    
            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;
        private final Object lock = new Object();
    
        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 void runAnalysis(int index) {
            synchronized(lock) {
                if(concurrentMap.containsKey(index)) {
                    System.out.println("contains integer " + index);
                } else {
                    System.out.println("put " + index + " thread " + thread);
                    concurrentMap.put(index, "thread " + thread);
                }
            }
        }
    }
    

    results

    put 0 thread 0
    contains integer 0
    put 1 thread 7
    put 2 thread 7
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    key 0 thread 0
    key 2 thread 7
    key 1 thread 7
    
    0 讨论(0)
  • 2020-12-21 23:44

    If you make a new class "RunAnalysis" and add the code of method runAnalysis() in that class like this:

    class RunAnalysis {
        public synchronized void analyse(ConcurrentHashMap<Integer, String> concurrentMap, int thread, 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);
            }
        }
    }
    
    public class SyncExample implements Runnable {
        RunAnalysis runAnalysis = new RunAnalysis();
        ConcurrentHashMap<Integer, String> concurrentMap;
        private int thread;
    
        public SyncExample(ConcurrentHashMap<Integer, String> concurrentMap, int     thread) {
            this.concurrentMap = concurrentMap;
            this.thread = thread;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                runAnalysis.analyse(concurrentMap, thread, i);
            }
        }
    }
    

    then the output is:

    put 0 thread 1
    put 1 thread 1
    put 2 thread 1
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    contains integer 0
    contains integer 1
    contains integer 2
    key 0 thread 1
    key 1 thread 1
    key 2 thread 1
    
    0 讨论(0)
提交回复
热议问题