Skip to content

Fix ConcurrentModificationException while calling emitBufferedMarks in Android #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

vivs-nitjsr
Copy link
Collaborator

@vivs-nitjsr vivs-nitjsr commented Jul 18, 2022

Fix ConcurrentModificationException while calling emitBufferedMarks in Android

Currently, we are getting exception ConcurrentModificationException while calling emitBufferedMarks. The ArrayList is currently iterated and removed in the loop. To fix this iterator can be used, which checks if the element is present in the iterator before processing it. To solve the concurrency on multi threaded environment need to use some concurrent list. Here ConcurrentLinkedQueue can be used to solve the ConcurrentModificationException with the iterator.

@vivs-nitjsr vivs-nitjsr force-pushed the fix-concurrentmodificationexception-crash-android branch from aca714e to c6b45d0 Compare July 18, 2022 10:28
@vivs-nitjsr vivs-nitjsr requested a review from oblador July 18, 2022 10:28
@vivs-nitjsr vivs-nitjsr self-assigned this Jul 18, 2022
@vivs-nitjsr vivs-nitjsr added the bug Something isn't working label Jul 18, 2022
@vivs-nitjsr vivs-nitjsr force-pushed the fix-concurrentmodificationexception-crash-android branch from c6b45d0 to 0b18a21 Compare July 18, 2022 10:30
@opayen
Copy link
Contributor

opayen commented Jul 18, 2022

I don't think that this will fix the issue. The way iterators work is that they keep a representation of the list's state, and if there is a change made without using this iterator's methods, a ConcurrentModificationException exception is thrown.
Since you use different iterator instances, structural changes will happen from outside, so it will still crash.

Maybe we can use a ConcurrentLinkedQueue instead of an ArrayList?

Otherwise if we still need a List and what we have is write-often - read occasionally, maybe we could use a synchronised copy-on-read collection like this one.

@vivs-nitjsr
Copy link
Collaborator Author

Hi @opayen , I tested it on demo app. I used Iterator with ConcurrentLinkedQueue works perfectly. Iterator with ArrayList was still having the ConcurrentModificationException on multiple threads. I will update the PR with the ConcurrentModificationException.

Demo app that I used is below:

import java.util.Iterator;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue;

public class Test {
    
    private static Test instance = null;
    private Queue<String> strs = new ConcurrentLinkedQueue<>();

    private static String [] strings = {"Hello", "How", "are", "you", "doing"};

    public static Test getInstance() {
        if (null == instance) {
            instance = new Test();
        }

        return instance;
    }

    public void addElement(String str) {
        strs.add(str);
    }

    public void removeElement(String str) {
        if(strs.contains(str)) {
            strs.remove(str);
        }
    }

    public static void main (String[] args) {
        for (int j = 0; j < 10; j++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        int index = new Random().nextInt(strings.length);
                        String s = strings[index];
                        if(i % 2 == 0) {
                            Test.getInstance().addElement(s);
                        } else {
                            Test.getInstance().removeElement(s);
                        }
                        Test.getInstance().printValues();
                    }  
                }
            });
            thread.start();
        }
        
    }

    public void printValues() {
        String p = "";
        Iterator<String> iterator = strs.iterator();
        while (iterator.hasNext()) {
            p += iterator.next() + " ";
        }
    }
}

@vivs-nitjsr vivs-nitjsr force-pushed the fix-concurrentmodificationexception-crash-android branch from 0b18a21 to b7a31cb Compare July 18, 2022 15:18
@vivs-nitjsr vivs-nitjsr merged commit 765ecf1 into master Jul 25, 2022
@vivs-nitjsr vivs-nitjsr deleted the fix-concurrentmodificationexception-crash-android branch July 25, 2022 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants