Impact of one synchronized from another synchronized method in multi-thread environment? - java

I am working with the synchronization threads where I have three synchronized method and each method will access by individual thread (Total 3 threads in current program )
In our program we are calling one syn method is calling another sync method, below is sample code which is inspired from real application :
public class ThreadTest {
public static synchronized void suncMessage() {
System.out.print("1");
}
public static synchronized void suncMessage2() {
suncMessage();
System.out.print("2");
}
public static synchronized void suncMessage3(String s) {
System.out.print("3m" + s);
}
public static void main(String... at) throws InterruptedException {
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage();
}
}
};
Thread t2 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage2();
}
}
};
Thread t3 = new Thread() {
public void run() {
for (int i = 0; i <= 2; i++) {
suncMessage3("3");
}
}
};
t1.start();
t2.start();
t3.start();
}
}
So my question is, what is impact of calling one synch. method from another synch.?? Is it good practices and how it will impact the complexity of program?

Nice question, but you have to try hard when you are working on this type of scenarios and the performance may effect. Because synchronization is approx 50 time slower than normal method.

Related

Java multi-threading synchronization [duplicate]

This question already has answers here:
why doesn't this synchronized method work as expected?
(3 answers)
Closed 5 years ago.
I am learning synchronization in java. Got struck in the below sample code today.
In the below code, test() method is made synchronized. So, I assume th1's test() invocation would complete and then th2's test() invocation would start. However, it is not happening that way. The outputs are interweaved. Can you please help me understand why ?
public class MyThread {
public static void main(String[] args)
{
SampleThread sample = new SampleThread("one");
Thread th = new Thread(sample);
th.start();
SampleThread sample2 = new SampleThread("two");
Thread th2 = new Thread(sample2);
th2.start();
}
}
class SampleThread implements Runnable
{
public SampleThread(String name)
{
this.name=name;
}
String name;
#Override
public void run() {
test();
}
public synchronized void test()
{
for(int j=0;j<10;j++)
{
System.out.println(name + "--" + j );
}
}
}
To sync threads you need common point to sync them. Create object, pass it to the threads, then you can syncronize on the object. If you need to wait on the object in first thread, and notify in second. First example from google.
The method test() is synchronized but it isn't invoked by multiple threads cause each thread has a distinct instance of SampleThread. Use a single SampleThread for both threads to get subsequent output.
public class MyThread {
public static void main(String[] args) {
final SampleThread sample = new SampleThread();
Thread th = new Thread(sample);
th.start();
Thread th2 = new Thread(sample);
th2.start();
}
}
class SampleThread implements Runnable {
#Override
public void run() {
test();
}
public synchronized void test() {
for (int j = 0; j < 10; j++) {
System.out.println(Thread.currentThread().getId() + "--" + j);
}
}
}

Synchronized block vs. synchronized method qualifier in Java

The following code
public class Coordination {
private volatile int counter = 0;
public static void main(String ... args) throws Exception {
new Coordination().volatileWithCoordination();
}
public synchronized void inc() {
counter++;
}
public void volatileWithCoordination() throws Exception {
Thread th1 = new Thread(new Runnable() {
#Override
public void run() {
for(int k = 0; k < 10_000_000; k++) {
synchronized(this) {
//inc();
counter++;
}
}
}});
Thread th2 = new Thread(new Runnable() {
#Override
public void run() {
for(int k = 0; k < 10_000_000; k++) {
//synchronized(this) {
inc();
//counter++;
//}
}
}});
th1.start();
th2.start();
th1.join();
th2.join();
System.out.println("counter: "+counter);
}
}
exhibits incorrect and non-deterministic result of counter: 18025867 whereas switching to:
inc();
//counter++;
in the Runnable of the first thread (th1) gives the expected output:
counter: 20000000
What's causing this lost update behavior and why would a synchronized method in this case behave differently to a synchronized(this) block?
Thank you in advance.
Your threads are synchronizing on different objects. Your th2 thread calls the synchronized inc() method, which synchronizes on an instance of the Coordination class; but when your th1 thread does synchronized(this), the this keyword refers to an instance of the anonymous inner Runnable class, not to the Coordination class.
Both threads need to acquire a monitor on the same object, the following change (on either of the 2 threads or both) fixes the situation:
synchronized(Coordination.this) {
inc();
//counter++;
}

Why synchronized method doesn't work in my case (or rather what is wrong with my assumption)?

I have this code:
import java.util.concurrent.atomic.AtomicLong;
interface Counter {
public void increment();
public void decrement();
public int value();
}
class SynchronizedCounter implements Counter {
private int c = 0;
#Override
public synchronized void increment() {
c++;
}
#Override
public synchronized void decrement() {
c--;
}
#Override
public synchronized int value() {
return c;
}
}
class UnsynchronizedCounter implements Counter {
private int c = 0;
#Override
public void increment() {
c++;
}
#Override
public void decrement() {
c--;
}
#Override
public int value() {
return c;
}
}
public class TestProjectApp {
public static void main(String[] args) {
AtomicLong unsynchronizedErrors = new AtomicLong();
AtomicLong synchronizedErrors = new AtomicLong();
for (int i = 0; i < 1000; i++) {
Counter c = new UnsynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
unsynchronizedErrors.incrementAndGet();
}
})).start();
}
for (int i = 0; i < 1000; i++) {
Counter c = new SynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
synchronizedErrors.incrementAndGet();
}
})).start();
}
System.out.println("Unsynchronized errors: " + unsynchronizedErrors);
System.out.println("Synchronized errors: " + synchronizedErrors);
}
}
The result of execution of my program is:
Unsynchronized errors: 83
Synchronized errors: 26
I understand why there are unsynchronized errors but I don't understand why I've got synchronized errors.
My assumption is that in the second loop the thread which increment number of synchronized errors is obligated to wait until the thread which use SynchronizedCounter::increment() method. What's wrong with the way I think?
Edit:
It seems that there is no need to make those method synchronized but it's enough to use Thread::join() method in second thread. But still I don't understand why it haven't worked.
Your assumption is wrong. synchronized guarantees that the executions of your methods will not be interleaved, and that they will have an ordering. You expect the threads to run in a specific order, but you are not enforcing the order in any way.
In your second loop, you expect the threads to reach the execution of the synchronized methods in the order in which the threads are created. But what can happen in the loop body
Counter c = new SynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
synchronizedErrors.incrementAndGet();
}
})).start();
is that the Thread that you created second (the synchronizedErrors checker) runs before the first one (the one that does the incrementing). You classify this as an error, but no error has happened.
edit
The best way to fix this is to join all threads that do incrementing/decrementing before querying the state of the counter.

Stop an algorithm in a thread after a given time has passed

Let's say that I have an algorithm that does something for a given parameter. If the algorithm runs longer than 100 miliseconds then I want to stop it and try again for a different parameter.
I posted below the code that would test the algorithm for a random parameter... and how I think the code might look like:
public class StopThread {
private Lock lock = new ReentrantLock();
public static void main(String... args) {
System.out.println("Starting threads...");
(new StopThread()).startThreads(100);
}
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
startThread(i, (long) (Math.random() * 10000000000l));
System.out.println("Started thread number " + (i + 1));
}
}
private void startThread(final int number, final long load) {
Thread workerThread = new Thread() {
#Override
public void run() {
try {
lock.lock();
doAlgorithmWork(load);
} finally {
System.out.println("Thread " + (number + 1) + " finished...");
lock.unlock();
}
}
};
Thread timerThread = new Thread() {
#Override
public void run() {
try {
sleep(100);
} catch (InterruptedException e) {
}
}
};
workerThread.start();
timerThread.start();
do {
if (!workerThread.isAlive() || !timerThread.isAlive()) {
workerThread.stop();
timerThread.stop();
}
} while (!workerThread.isAlive() && !timerThread.isAlive());
}
protected void doAlgorithmWork(long load) {
while (load-- > 0) {
}
}
}
I feel like this question should already have an answer, but what I found until now seemed complicated and I didn't know how to use it. I'm not that knowledgeable with threads and I would appreciate if you could post some code.
A very simple solution would look like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread() {
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
}
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
This will achieve your goal, but suffers from a number of "drawbacks"
It is single threaded (that is, all calls to doAlgorithm execute one after another, instead of in parallel, so you are only using a single core of your machine);
It uses the discouraged Thread.stop() method. A preferred approach is to instead have a "stop" flag which is set to true (in place of the stop() call), and which is also constantly checked for in doAlgorith;
It creates a new thread for each doAlgorithm call (instead of reusing a single thread), which is "wasteful", but for your case probably has little practical implications
UPDATE:
In order to avoid the deprecated stop() call, you will need to add a flag to your worker thread, creating a separate class like this:
public class Worker implements Runnable {
private volatile boolean stopped = false;
public void stop() {
stopped = true;
}
#Override
public void run() {
doAlgorithmWork((long) (Math.random() * 10000000000l));
}
private void doAlgorithmWork(long load) {
while (!stopped && load-- > 0) {
//calculation
}
}
}
Then your runner looks like this:
private void startThreads(int nrOfThreads) {
for (int i = 0; i < nrOfThreads; i++) {
Thread worker = new Thread(new Worker());
worker.start();
worker.join(100); //block until either the thread is done, or 100ms passed
if (worker.isAlive()) worker.stop(); //if thread is still alive, stop it
}
}
You could also create a constructor for Worker which accepts the load value (instead of having it generated inside the Worker itself).
Note that if the calculation inside doAlgorithm() is too time-consuming, the thread may run for more than 100ms (since it always completes each calculation within the loop). If this is an issue, then your alternative is to interrupt the thread instead (calling worker.interrupt() will cause an InterruptedException to be thrown within the run() method).

How to throttle method invocations to allow threads to complete

I currently have the following setup. I am getting out fo memory exceptions after it runs for a little while; I suspect the for loop in main is causing too much of a backup method calls. What is the best way to throttle the calls if I don't wish to increase the thread pool size?
public class ManagedThreads {
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
// method body using i
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 1000000000; ++i)
myMethod(i);
}
}
EDIT
I meant to show that I am passing in the index for the loop to the runnables.
You have ten threads so add ten jobs and you will never run out of memory trying to schedule them.
e.g.
public class ManagedThreads {
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
// do every tenth task.
for(int j = i; j < 1000000000; j += 10) {
// method body
}
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
myMethod(i);
}
}
I am getting out fo memory exceptions after it runs for a little while; I suspect the for loop in main is causing too much of a backup method calls. What is the best way to throttle the calls if I don't wish to increase the thread pool size?
This is a FAQ. See my answer here: Process Large File for HTTP Calls in Java
You need to define your own bounded job queue and then define a RejectedExecutionHandler. The following code will block when it tries to add more than 100 jobs to the job queue.
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// this will block the producer until there's room in the queue
executor.getQueue().put(r);
} catch (InterruptedException e) {
throw new RejectedExecutionException(
"Unexpected InterruptedException", e);
}
}
});
i would go with this (it will allow each worker to perform same amount of work in terms of cpu clocks)
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
final static AtomicInteger counter = new AtomicInteger(0);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
while (counter.getAndIncrement() < 1000000000) {
//method body
}
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
myMethod(i);
}
}
or do increments of 10 in each worker as Peter suggested. Saves a lot of objects and processing speed is high.

Categories