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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With