Multithread and Data Competition + Spring

0

I am rewriting software that serves as a bridge between two services. Communication is done via sockets. The environment it has high data competition, especially a list with active sockets. The software has some problems because this competition has not been handled correctly, causing some information to be shown to be wrong, or not delivered at some point in the communication.

As I am rewriting, I have some questions about the best and safest scenario.

Imagine the following: Multiple threads accessing a single list, being able to add, remove and iterate several times in the same second.

To solve this problem, I have created the following structure:

ServerService (Where would be the list that would be accessed by all threads)

@Component
public class ServerService {

    private CopyOnWriteArrayList<String> lista = new CopyOnWriteArrayList(new ArrayList<String>());

    public void add(String string, String myThreadName){
            System.out.println(myThreadName+". ADICIONANDO VALOR: "+string);
            lista.add(string);
    }

    public void remove(String string, String myThreadName){
            System.out.println(myThreadName+". REMOVENDO VALOR: "+string);
            lista.remove(string);
    }

    void printAll(String myThreadName){
        synchronized (lista){
            lista.forEach(s -> System.out.println(myThreadName+". ITERANDO VALUE: "+s));
        }
    }

    List<String> getAll(){
       return lista;
    }
}

MyRunnable (Where would be the control part of the sockets that would add, remove or 'iterate' the list)

public class MyRunnable implements Runnable{

    ServerService serverService;
    String myThreadName;


    @Autowired
    public MyRunnable(ServerService serverService, String myThreadName) {
        this.serverService = serverService;
        this.myThreadName = myThreadName;
    }


    @Override
    public void run() {
        while(true){
            String value = Double.toString(ThreadLocalRandom.current().nextInt(0, 10));
            serverService.add(value, myThreadName);
            serverService.printAll(myThreadName);
            serverService.remove(value, myThreadName);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

DemoApplication (Only one main to start)

@SpringBootApplication
public class DemoApplication implements ApplicationRunner {

    @Autowired
    ServerService serverService;

    @Autowired
    TaskExecutor taskExecutor;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        taskExecutor.execute(new MyRunnable(serverService, "THREAD 1"));
        taskExecutor.execute(new MyRunnable(serverService, "THREAD 2"));
    }
}

So, will I have the correct bidding behavior on the list?

Another question, how would I 'iterate' the list inside the thread, in a synchronized way, so that another thread can not add to the list when another one is iterating? Would that be the right way?

@Override
public void run() {
    while(true){
        String value = Double.toString(ThreadLocalRandom.current().nextInt(0, 10));
        serverService.add(value, myThreadName);
        synchronized (serverService.getAll()){ --ALTERAÇÃO AQUI
            serverService.getAll().stream().forEach(System.out::println);
        }
        serverService.remove(value, myThreadName);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

If necessary, I'll put more details.

    
asked by anonymous 28.11.2018 / 11:58

2 answers

1

Thread issues will always depend on the scenario!

However, it is important to know a useful stop mechanism, synchronized . This command causes only 1 thread to be executed at the same time.

With this, we can make a synchronized list so that it can only be modified with one thread at a time.

Use synchronized wisely! It is not interesting to put it at all, it can compromise your software and much.

Another output would be to create static controls, such as thread-related ids, list and operations ... But that is not the best option.

    
28.11.2018 / 13:20
0

- Operations that modify the list content must be synchronized. When you place a synchronized method it only allows one thread to run at a time. Hence it is important that your code is not all synchronized because it would always be just one thread to go through the code at a time. (Use / See the blocking queue implementation)

-Why? For example, when you remove something from the list and decrease the size of the list (i--), let's assume that you need 3 sub-actions to decrement the size of the list (fetch the value of i, decrease it, and update its value), if two threads do this action at the same time it may be that while one is removing from the list, the other has already made the first two sub-actions and has not yet updated the new value of ie will only update after the other fetch the value of io that was not correct (the thread was going to fetch an out-of-date value).

    
10.12.2018 / 23:59