Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing usage of Synchronization with 2 Threads in Java

I've been looking about multi threading tutorials and those specific about synchronization, but I haven't been able to implement something that I need.

It's a showcase of a synchronization happening in my program.

Basically, I have one class that inherits some functions from other class, those functions needs to be synchronized in order for both of threads doesn't modify an object at the same time (no data corruption).

I previously implemented the code without the synchronize keyword, so I could manage to see the data corruption occurring.

 EditOptionsMethods e1;
    int threadNo;

    public EditOptions() {
        e1 = new BuildAuto();
        run();
    }

    public void run() {
        System.out.println("Thread running.");

        switch (threadNo) {
            case 0:

                break;

            case 1:
                break;
        }

    }

    public void setOptions(String optSetName1, String desiredOption1, String optSetName2, String desiredOption2) {
        e1.s_Option(optSetName1, desiredOption1); // 
        e1.s_Option(optSetName2, desiredOption2);
    }

s_Option will have to be synchronized so both threads won't occur. I firstly will have it without synchronize, then I can initialize a loop (with high index amount, lets say 1000 and then I add with first thread, and subtract with second thread) to see the corruption occurring as an example.

But I don't find a way of showing this.

If someone has an idea of how I could possibly implement this, that'd be awesome.

like image 821
Woldev Avatar asked Dec 06 '20 09:12

Woldev


People also ask

Which is used for synchronizing multiple threads?

Java provides a way of creating threads and synchronizing their task by using synchronized blocks. Let us start with our example. We will be working with a Counter class, that has nothing but just a count member variable and a method incr() which increments the value of count variable by one.

How do I sync two threads?

Here's what I got: final Object lock = new Object(); final Thread t = new Thread(new Runnable() { public void run() { synchronized(lock) { System. out. println("qwerty"); lock.

What will happen if a synchronized method is called by two threads?

No. If a object has synchronized instance methods then the Object itself is used a lock object for controlling the synchronization. Therefore all other instance methods need to wait until previous method call is completed.

What is synchronization how it is useful in multithreading in Java?

Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads.

How do you synchronize multiple threads in Java?

Thread Synchronization in Java The process of allowing multiple threads to modify an object in a sequence is called synchronization. We can allow multiple threads to modify the objects sequentially only by executing that objects’ mutator methods logic in sequence from multiple threads. This is possible by using an object locking concept.

What is synchronization in Java and how it works?

Synchronization is build using locks or monitor. In Java, a monitor is an object that is used as a mutually exclusive lock. Only a single thread at a time has the right to own a monitor. When a thread gets a lock then all other threads will get suspended which are trying to acquire the locked monitor.

What is the use of synchronized method in threading?

Synchronized method is used to lock an object for any shared resource. When a thread invokes a synchronized method, it automatically acquires the lock for that object and releases it when the thread completes its task. In this program, we have created the two threads by annonymous class, so less coding is required.

How to allow multiple threads to modify an object sequentially?

The process of allowing multiple threads to modify an object in a sequence is called synchronization. We can allow multiple threads to modify the objects sequentially only by executing that objects’ mutator methods logic in sequence from multiple threads. This is possible by using an object locking concept.


1 Answers

First create a structure that will hold the threads:

   List<Thread> threads = new ArrayList<>();

then initialize it, and assign work to the threads:

   int total_threads = 2;
   for(int i = 0; i < total_threads; i++){
       Thread thread  = new Thread(() -> {
           // the work to be done by the threads
       });
       threads.add(thread);
   }

Run the threads:

threads.forEach(Thread::start);

Finally, wait for the threads to finish their work:

   threads.forEach(t -> {
       try {
                t.join();
       } catch (InterruptedException e) {
                e.printStackTrace();
        }
   });

With a running example:

import java.util.*;

public class SomeClass {

    private int x;

    public void addX(int y){ x = x + y;}


    public static void main(String[] args) {
           SomeClass example = new SomeClass();
           List<Thread> threads = new ArrayList<>();
           int total_threads = 2;
           for(int i = 1; i < total_threads + 1; i++){
               final int threadID = i;
               Thread thread  = new Thread(() -> {
                   for(int j = 0; j < 1000; j++ )
                    example.addX((threadID % 2 == 0) ? -threadID : threadID);
               });
               threads.add(thread);
           }
           threads.forEach(Thread::start);
           threads.forEach(t -> {
               try {
                        t.join();
               } catch (InterruptedException e) {
                        e.printStackTrace();
                }
           });
           System.out.println(example.x);
    }
}

Now try to run the example above with and without synchronizing the work done by the threads:

   Thread thread  = new Thread(() -> {
   for(int j = 0; j < 1000; j++ )
       example.addX((threadID % 2 == 0) ? -threadID : threadID);
   });

versus:

 Thread thread  = new Thread(() -> {
 synchronized(example){ // <-- adding synchronization 
    for(int j = 0; j < 1000; j++ )
      example.addX((threadID % 2 == 0) ? -threadID : threadID);
   }
 });

With the version that uses synchronization, you can run the code as many times as you want the output will always be -1000 (using 2 threads). However, with the version without the synchronization the output will be non-deterministic due to the race condition happening during the updates of the variable x.

Instead of using the Thread class directly, you can opt for a higher abstraction, namely executors:

public class SomeClass2 {

  private int x;

  public void addX(int y){x = x + y;}

  public static void main(String[] args) {
      SomeClass2 example = new SomeClass2();
      int total_threads = 2;
      ExecutorService pool = Executors.newFixedThreadPool(total_threads);
      pool.execute(() -> {
         synchronized (example) {
            parallel_task(example, -2);
        }
      });
      pool.execute(() -> {
        synchronized (example) {
            parallel_task(example, 1);
         }
      });

      pool.shutdown();
      try { pool.awaitTermination(1, TimeUnit.MINUTES);} 
      catch (InterruptedException e) {e.printStackTrace();}  
      System.out.println(example.x);
}

private static void parallel_task(SomeClass2 example, int i) {
    thread_sleep();
    for (int j = 0; j < 1000; j++)
        example.addX(i);
}

private static void thread_sleep() {
    try { Thread.sleep(1000); } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }
 }
}

I have added the thread_sleep() to ensure that both parallel tasks are not pick up by the same thread from the thread pool.

like image 194
dreamcrash Avatar answered Oct 15 '22 16:10

dreamcrash