I am very new to multithreading, was trying a scenario in which a home has a mother(as producer),son,daughter and husband[As consumer] thread.I am trying to understand how wait and notify method can help here.
My classes are as below.
MotherAsProducer
package com.test.All.Threads;
public enum MotherAsProducer {
INSTANCE;
/*
*
*
* son Give request to prepare chapati to mother
* mother accepts it and start preparing , son/husband/daughter should wait by that time.
* mother notifies son/daughtor/husband that chapati is ready start consuming
* */
public synchronized void takeOrderAndMakeChapati(){
try {
System.out.println("Request got from "+Thread.currentThread().getName());
getStatusOfChapati();
wait();
System.out.println(Thread.currentThread().getName()+" ate chapati");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//lock re-entrance
public synchronized void getStatusOfChapati(){
try {
Thread.sleep(1200);
System.out.println("Chapati is prepared for "+Thread.currentThread().getName());
notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static MotherAsProducer getMotherInstance(){
return MotherAsProducer.INSTANCE;
}
}
SonAsConsumer class
package com.test.All.Threads;
public class SonAsConsumer implements Runnable{
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
DaughterAsConsumer class
package com.test.All.Threads;
public class DaughterAsConsumer implements Runnable {
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
HusbandAsConsumer class
package com.test.All.Threads;
public class HusbandAsConsumer implements Runnable {
public void run(){
MotherAsProducer.getMotherInstance().takeOrderAndMakeChapati();
}
}
Home class
package com.test.All.Threads;
public class Home {
public static void main(String args[]){
SonAsConsumer sac = new SonAsConsumer();
DaughterAsConsumer dac = new DaughterAsConsumer();
HusbandAsConsumer hac = new HusbandAsConsumer();
Thread tsac = new Thread(sac);
tsac.setName("Son");
Thread tdac = new Thread(dac);
tdac.setName("Daughter");
Thread thac = new Thread(hac);
thac.setName("Husband");
tsac.start();
tdac.start();
thac.start();
}
}
My output is different, every time as expected by nature of thread but one of the individual either husband, daughtor or son is not getting complete.
one instance of my output is as below.
Order she got from Daughter
Chapati is prepared for Daughter
Order she got from Son
Chapati is prepared for Son
Order she got from Husband
Chapati is prepared for Husband
Son ate chapati
Daughter ate chapati
My understanding here is when son,daughter and husband will start executing one of them will hit the synchronized method and execute wait() and will hold the lock , from that synchronized method again another synchronized method is called which will contain notify and the lock will be released and another thread will try to get the lock from the blocked pool and will execute in the same manner . here two threads are behaving as expected but the last one is not.
Kindly help here.
Briefly looking, it looks like the last thread to get to the wait will never get notified. Sequencing your calls you have each thread getting a lock, notifying all waiting threads, and then waiting. So, the last thread that hits the wait will never have anyone to notify them that they need to exit.
That is, if Thread A gets the lock initially, then it will do a println and a sleep then a println, then notify all waiting threads (there are none), and then become a waiting thread.
Then, lets say Thread B gets the lock. It will do a println and a sleep, then it will notify all (which will "notify" Thread A), then it will wait.
Now, either Thread C or Thread A will get the lock. If Thread A gets it, it will simply fall through and complete with the "ate" message. Then, Thread C can get the lock and it will eventually notify, waking B which can eat once C "waits". Now, there is no thread left to notify so that C will complete.
This make sense? Did I misread anything?
To verify what I'm suggesting is wrong, simply add in more threads. You should always have the last one that prints "Chapati is prepared for ..." will never eat it.
Fundamentally, I think the confusion is that "Mother" is not actually doing any work. What you probably wanted is to have "Mother" be a thread that has its own work log. So, when one of the other threads gives her work, you set a variable then notify mother and wait as the sibling. The mother will then wake up and do the work and notify the current thread waiting.
See what I mean? Metaphorically, you have 4 people in this program. But, you only have 3 threads.
Change the method in the enum class MotherAsProducer as follows: The unnecessary wait() method caused the issue. Since the method is synchronized, all other threads will be blocked before entering into the method until getting a notification from lock holding thread.
public synchronized void takeOrderAndMakeChapati() {
System.out.println("Request got from " + Thread.currentThread().getName());
getStatusOfChapati();
// wait(); - THIS WAIT IS CAUSING THE PROBLEM
System.out.println(Thread.currentThread().getName() + " ate chapati");
}
Remove wait and notifyAll calls from both takeOrderAndMakeChapati and getStatusOfChapati. You will get the expected result.
As precisely mentioned by Josh, one of the threads (last one) is still waiting for some external notification, and there is nobody to notify. You code is still running in the background. Just call wait(5000) and you can see it happening.
Both methods takeOrderAndMakeChapati and getStatusOfChapati are synchronized, therefore synchronization is not the issue.
Generally threads wait for some external dependency or condition, where some other thread(s) notifies the waiting one, when that condition is fulfilled.
I also tried to understand wait and notify when I started with multithreading. But as soon as I learned to use a Semaphore, I never looked back. Hopefully, the example below will give you some insight into the benefits of using a Semaphore. There is also a lot more useful stuff in the java.util.concurrent package that can be of great help.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class EatChapati {
static int CHAPATI_PREPARE_TIME_MS = 100;
static long RUN_TIME_MS = 2000;
static long SHUTDOWN_TIME_MS = 500;
static int CHAPATI_CONSUMERS = 5;
static volatile boolean stop;
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
for (int i = 0; i < CHAPATI_CONSUMERS; i++) {
executor.execute(new ChapatiConsumer(i + 1));
}
try { Thread.sleep(RUN_TIME_MS); } catch (Exception ignored) {}
stop = true;
executor.shutdownNow();
try { executor.awaitTermination(SHUTDOWN_TIME_MS, TimeUnit.MILLISECONDS); } catch (Exception ignored) {}
}
// 1 producer making chapati's
// 'true' for a fair semaphore: longest waiting consumer gets served
static Semaphore chapatiTurn = new Semaphore(1, true);
static AtomicInteger chapatiCount = new AtomicInteger();
static int getChapati(int consumerNumber) {
int chapatiNumber = 0;
boolean haveTurn = false;
try {
chapatiTurn.acquire();
// start of 'synchronized' block
haveTurn = true;
Thread.sleep(CHAPATI_PREPARE_TIME_MS);
chapatiNumber = chapatiCount.incrementAndGet();
System.out.println("Chapati " + chapatiNumber + " prepared for consumer " + consumerNumber);
} catch (Exception e) {
// Triggered by executor.shutdownNow
stop = true;
} finally {
if (haveTurn) {
chapatiTurn.release();
// end of 'synchronized' block
}
}
return chapatiNumber;
}
static class ChapatiConsumer implements Runnable {
int number;
ChapatiConsumer(int number) {
this.number = number;
}
public void run() {
int chapatisConsumed = 0;
while (!stop) {
if (getChapati(number) > 0) {
chapatisConsumed++;
}
}
System.out.println("Consumer " + number + " stopped after consuming " + chapatisConsumed + " chapatis.");
}
}
}
Related
I am trying to print out the content of arraylist using 2 threads, my main goal is to make threads read arraylist in a synchronized way and print its content. Eventhough I use synchronized block, I still am getting IllegalMonitorStateException. I know this is a basic question but I can not get it working, pardon me.
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Q1 {
public static Q1 yeni;
public static void main(String[] args) {
// TODO Auto-generated method stub
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
ExecutorService executorService = Executors.newFixedThreadPool(10);
synchronized (list) {
myThread thread1 = new myThread(list);
myThread thread2 = new myThread(list);
thread1.start();
thread2.start();
}
}
}
And here is myThread class
import java.util.*;
public class myThread extends Thread {
List<String> liste;
public myThread(List<String> liste) {
this.liste = liste;
}
#Override
public void run() {
try {
synchronized (Q1.yeni) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
this.wait(3000);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The reason for the IllegalMonitorStateException is that you are calling wait on an object (this) without holding the monitor for that object. You must either wrap this call with a synchronized (this) block, or call wait on Q1.yeni, which this code already has synchronized.
However, it looks like the use of wait might be mistaken. This method is used to wait on a condition, which is signaled with a call to notify or notifyAll on the same object. Since there is no apparent condition in this code, and no usages of notify or notifyAll, I suspect that what you really want to call is this.sleep(3000), which pauses the thread for three seconds, then resumes it after that duration elapses.
The sleep method does not require ownership of any monitors, and does not release ownership of held monitors, so another thread would not be able to enter the synchronized (Q1.yeni) block while one is currently sleeping. This implies that the first thread to enter that block will run to completion, iterating through the entire list, before the second thread has a chance to begin. It's not totally clear if that's what is intended here.
See the documentation for Object.wait and Thread.sleep for more usage information.
A second problem is that Q1.yeni is accessed by these threads before it is necessarily initialized, because the threads are started in the Q1 constructor, and the statement yeni = new Q1(); only assigns yeni after the constructor completes. In this case, it might be better for the threads to use synchronized (liste) instead.
Other than that, having synchronized (list) in the Q1 constructor does not accomplish much, since the main thread does not access or manipulate the contents of list in that section. The only practical effect is that the threads it starts will block when they reach the first call to liste.size() until the main thread exits the synchronized (list) (immediately after starting the two threads). This has the potential to slightly slow down the first thread that runs, but has no effect on the thread-safety or correctness of the program.
I would also recommend reviewing "How to Handle InterruptedException in Java". In this case, I would recommend restoring the interruption status in the exception handler.
Put together, here is a revised example of this code (including other minor changes to remove unused code and boilerplate comments, improve formatting, and ensure consistency with Java naming conventions):
Q1.java:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Q1 {
private static Q1 yeni;
public static void main(String[] args) {
yeni = new Q1();
}
Q1() {
List<String> list = Collections.synchronizedList(new ArrayList<>());
list.add("a1");
list.add("b1");
list.add("c1");
list.add("d1");
list.add("e1");
list.add("f1");
MyThread thread1 = new MyThread(list);
MyThread thread2 = new MyThread(list);
thread1.start();
thread2.start();
}
}
MyThread.java:
import java.util.*;
public class MyThread extends Thread {
private final List<String> liste;
public MyThread(List<String> liste) {
this.liste = liste;
}
#Override
public void run() {
try {
synchronized (liste) {
System.out.println("Thread number " + this.getName() + " started running.");
for (int i = 0; i < liste.size(); i++) {
System.out.println(liste.get(i));
sleep(3000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
interrupt();
}
}
}
Output:
Thread number Thread-0 started running.
a1
b1
c1
d1
e1
f1
Thread number Thread-1 started running.
a1
b1
c1
d1
e1
f1
Recently I've started looking into multithreading, and I have a question, perhaps more experienced ones could help.
My program creates two parallel threads, each of them prints counts from 0 to 19 (the NumbersPrinter class, which implements the Runnable interface).
class NumbersPrinter implements Runnable {
private Mediator mediator;
private String name;
private int makeActionOnCount;
public NumbersPrinter(Mediator mediator, String name, int makeActionOnCount) {
this.mediator = mediator;
this.name = name;
this.makeActionOnCount = makeActionOnCount;
}
#Override
public void run() {
for(int i = 0; i<20; i++){
try {
synchronized(this.mediator) {
if(this.mediator.actionInProgress.get()) {
System.out.println(name + " waits");
wait();
}
}
System.out.println(this.name + " says " + i);
Thread.sleep(500);
if(i == makeActionOnCount) {
synchronized(this.mediator) {
System.out.println(this.name + " asks Mediator to perform action...");
this.mediator.performAction();
this.mediator.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
When one of the threads reaches a certain number (defined in the makeActionOnCount variable), it starts performing a certain action that stops the execution of the second counter. The action lasts 5 seconds and after that both counters continue to count.
The counters are interconnected through an instance of the Mediator class, the performAcyion() method also belongs to the instance of the Mediator class.
import java.util.concurrent.atomic.AtomicBoolean;
class Mediator {
public AtomicBoolean actionInProgress = new AtomicBoolean(false);
public Mediator() {
}
public void performAction() throws InterruptedException {
actionInProgress.set(true);
System.out.println("Action is being performed");
Thread.sleep(5000);
System.out.println("Action has been performed");
actionInProgress.set(false);
}
}
Here's the Main class:
class Main {
public static void main(String[] args) throws InterruptedException{
Mediator mediator = new Mediator();
NumbersPrinter data = new NumbersPrinter(mediator, "Data", 10);
NumbersPrinter lore = new NumbersPrinter(mediator, "Lore", 5);
Thread oneThread = new Thread(data);
Thread twoThread = new Thread(lore);
System.out.println("Program started");
oneThread.start();
twoThread.start();
oneThread.join();
twoThread.join();
System.out.println("Program ended");
}
The way the program is written now - works fine, but I don't quite understand what exactly should I write in the first synchronized block, because if you delete all content from it, the program still works, since the counter that does not execute the performAction() method stops 'cause the counter cannot access the monitor of the Mediator object 'cause it is busy with the parallel counter. AtomicBoolean variable and checking it also makes no sense.
In other words, I may not use the wait () and notify () constructs at all, as well as the value of the AtomicBoolean variable, and just check access to the Mediator object's monitor every new iteration using an empty synchronized block. But I've heard that an empty synchronized block is a bad practice.
I am asking for help on how to rewrite the program to use the synchronized block and the wait() and notify() methods correctly.
Maybe I'm syncing on the wrong object? How would you solve a similar problem?
Thanks in advance
In my applications there are an n number of actions that must happen, one after the other in sequence, for the whole life of the program. Instead of creating methods which implement those actions and calling them in order in a while(true) loop, I decided to create one thread for each action, and make them execute their run method once, then wait until all the other threads have done the same, wait for its turn, and re-execute again, and so on...
To implement this mechanism I created a class called StatusHolder, which has a single field called threadTurn (which signifies which thread should execute), a method to read this value, and one for updating it. (Note, this class uses the Singleton design pattern)
package Test;
public class StatusHolder
{
private static volatile StatusHolder statusHolderInstance = null;
public static volatile int threadTurn = 0;
public synchronized static int getTurn()
{
return threadTurn;
}
public synchronized static void nextTurn()
{
System.out.print("Thread turn: " + threadTurn + " --> ");
if (threadTurn == 1)
{
threadTurn = 0;
}
else
{
threadTurn++;
}
System.out.println(threadTurn);
//Wake up all Threads waiting on this obj for the right turn to come
synchronized (getStatusHolder())
{
getStatusHolder().notifyAll();
}
}
public static synchronized StatusHolder getStatusHolder()
{//Returns reference to this object
if (statusHolderInstance == null)
{
statusHolderInstance = new StatusHolder();
}
return statusHolderInstance;
}
}
Then I have, let's say, two threads which must be execute in the way explained above, t1 and t2.
T1 class looks like this:
package Test;
public class ThreadOne implements Runnable
{
#Override
public void run()
{
while (true)
{
ThreadUtils.waitForTurn(0);
//Execute job, code's not here for simplicity
System.out.println("T1 executed");
StatusHolder.nextTurn();
}
}
}
And T2 its the same, just change 0 to 1 in waitForTurn(0) and T1 to T2 in the print statement.
And my main is the following:
package Test;
public class Main
{
public static void main(String[] args) throws InterruptedException
{
Thread t1 = new Thread(new ThreadOne());
Thread t2 = new Thread(new ThreadTwo());
t1.start();
t2.start();
}
}
So the run method goes like this:
At the start of the loop the thread looks if it can act by checking the turn value with the waitForTurn() call:
package Test;
public class ThreadUtils
{
public static void waitForTurn(int codeNumber)
{ //Wait until turn value is equal to the given number
synchronized (StatusHolder.getStatusHolder())
{
while (StatusHolder.getTurn() != codeNumber)
{
try
{
StatusHolder.getStatusHolder().wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
If the two values are equal, the thread executes, otherwise it waits on the StatusHolder object to be awaken from the nextTurn() call, because when the turn value changes all the threads are awaken so that they can check if the new turn value is the one they are waiting for so they can run.
Note thatnextTurn() cycles between 0 and 1: that is because in this scenario I just have two threads, the first executes when the turn flag is 0, and the second when its 1, and then 0 again and so on. I can easily change the number of turns by changing this value.
The problem: If I run it, all goes well and seems to work, but suddenly the output console stops flowing, even if the program doesn't crash at all. I tried to put a t1.join() and then a print in the main but that print never executes, this means that the threads never stop/dies, but instead they remain locked sometimes.
This looks to be even more evident if I put three threads: it stops even sooner than with two threads.
I'm relatively new to threads, so I might be missing something really stupid here...
EDIT: I'd prefer not to delete a thread and create a new one every time: creating and deleting thousands of objs every second seems a big work load for the garbage collector.
The reason why I'm using threads and not functions is because in my real application (this code is just simplified) at a certain turn there actually are multiple threads that must run (in parallel), for example: turn 1 one thread, turn 2 one thread, turn 3 30 threads, repeat. So I thought why not creating threads also for the single functions and make the whole think sequential.
This is a bad approach. Multiple threads allow you to execute tasks concurrently. Executing actions "one after the other in sequence" is a job for a single thread.
Just do something like this:
List<Runnable> tasks = new ArrayList<>();
tasks.add(new ThreadOne()); /* Pick better names for tasks */
tasks.add(new ThreadTwo());
...
ExecutorService worker = Executors.newSingleThreadExecutor();
worker.submit(() -> {
while (!Thread.interrupted())
tasks.forEach(Runnable::run);
});
worker.shutdown();
Call worker.shutdownNow() when your application is cleanly exiting to stop these tasks at the end of their cycle.
you can use Semaphore class it's more simple
class t1 :
public class t1 implements Runnable{
private Semaphore s2;
private Semaphore s1;
public t1(Semaphore s1,Semaphore s2){
this.s1=s1;
this.s2=s2;
}
public void run()
{
while (true)
{
try {
s1.acquire();
} catch (InterruptedException ex) {
Logger.getLogger(t1.class.getName()).log(Level.SEVERE, null, ex);
}
//Execute job, code's not here for simplicity
System.out.println("T1 executed");
s2.release();
}
}
}
class t2:
public class t2 implements Runnable{
private Semaphore s2;
private Semaphore s1;
public t2(Semaphore s1,Semaphore s2){
this.s1=s1;
this.s2=s2;
}
public void run()
{
while (true)
{
try {
s2.acquire();
} catch (InterruptedException ex) {
Logger.getLogger(t2.class.getName()).log(Level.SEVERE, null, ex);
}
//Execute job, code's not here for simplicity
System.out.println("T2 executed");
s1.release();
}
}
}
class main:
public class Testing {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Semaphore s2=new Semaphore(0);
Semaphore s1=new Semaphore(1);
Thread th1 = new Thread(new t1(s1,s2));
Thread th2 = new Thread(new t2(s1,s2));
th1.start();
th2.start();
}}
Why doesn't thread wait for notify()? The thread starts and then goes to the waiting pool, but it proceeds to execute after that moment.
public class JavaApplication2 {
public static void main(String [] args) {
ThreadB b = new ThreadB();
synchronized(b) {
b.start();
try {
System.out.println("1");
b.wait();
} catch (InterruptedException e) {}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
synchronized(this) {
total += 1;
//notify();
}
}
}
You are synchronizing on the thread object itself, which is wrong usage. What happens is that the dying thread-of-execution always calls notify on its Thread object: Thread.join relies on this. Therefore it is clear why you get the same behavior with and without your own notify in there.
Solution: use a separate object for thread coordination; this is the standard practice.
The method notifyAll() is invoked for the Thread object of the terminating thread. This fact is strangely documented in the description of the Thread.join, with the following sentence:
As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Thus, if you don't explicitly read the description of join, which you don't necessarily have to, you don't get to know the reason for the strange behavior.
You cannot depend on not returning from wait until a notify: "interrupts and spurious wakeups are possible". In general, you should wrap a wait call in a loop while the thread should go on waiting.
If you try your code synchronizing on any object other that ThreadB you will find it never terminates. This is because there is a hidden call to notify.
Although I am not aware of anywhere that this is specified, Thread notifies itself when it ends. This is implicit in the way the join method is implemented. This is the code for join:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
(From the JDK7 source code)
As you can see, the calls to wait only make sense if somewhere there is a call to notify that is called after the thread ends. The same call to notify is what allows your program to terminate.
You have nested synchronized {} constructs in the two places. These constructs seem doing something weird: the thread does not react into notify at all and only resumes when ThreadB (b) terminates. Remove this:
public class JavaApplication2 {
public static void main(String[] args) {
ThreadB b = new ThreadB();
b.start();
try {
System.out.println(" ### Waiting for notify");
synchronized (b) {
b.wait();
}
System.out.println(" ### Notified");
} catch (InterruptedException e) {
}
System.out.println("### Total is: " + b.total);
}
}
class ThreadB extends Thread {
int total;
#Override
public void run() {
total += 1;
System.out.println(" *** Ready to notify in 5 secs");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** Notification sent");
synchronized (this) {
notify();
}
System.out.println(" *** 5 sec post notification");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(" *** ThreadB exits");
}
}
The code above probably works correctly: with notify() present the main thread resumes after 5 seconds and before we see the message that ThreadB terminates. With notify() commented out the main thread resumes after 10 seconds and after the message about the termination of the ThreadB because notify() is called anywhay from the other code. Marko Topolnik explains why and from where this "behind the scene" notify() call comes from.
I was doing the same testing on the wait/notify opertaions while reading OCP SE 7, good catch. I think we should let the authoer to explain.
class A {
private synchronized f() {
...
...
}
private void g() {
...
...
}
}
If thread T1 is running f() which is synchronized, can thread t2 run g() which is not synchronized at the same point of time, while T1 is still running f()?
Not on the same instance of A. The instance itself is the lock so two execute the two methods at the same time with two threads you would need two instances of A.
Yes. Both methods can execute at the same time on the same instance.
Only f() is synchronized. A thread must acquire the monitor for this.f() to execute f() and only one monitor exists per instance.
g() is not synchronized, no monitor locking is required to run the method, so any thread can execute g() at any time.
"A synchronized method acquires a monitor (ยง17.1) before it executes."
http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.3.6
No. One call will block until the other completes. The reason for this is that the synchronized keyword on a method expands to synchronize on the current instance of the object. To be more specific, consider this code:
private void synchronized f() {
...
}
The above code is identical in functionality to the following code:
private void f() {
synchronized (this) {
...
}
}
So if you want two methods in an object to be synchronized only to each other, you should create two lock objects. Each method should wrap all of its code inside a synchronized (object) block, one object for each method.
Yes, if T1 and T2 are executing f and g respectively on different instances of A.
If both threads are executing a method on the same instance of A, only one will be able to execute a method at a time. If T1 runs first, it will acquire the lock on the instance of A, and execute method f. Thread T2 will be unable to execute method g until after T1 has finished executing f. Or the opposite could happen: T2 could run g first, and T1 won't be able to run f until after T2 has finished.
In general, two threads can run two methods at the same point in time; however, in your example only one thread might be running f() or g() at any given moment.
Using the synchronized keyword changes thread interactions. Every java object has a lock, an item that only one thread can hold at any given time. Synchronized is a command that directs the threads to acquire the lock before execution of a method and release it afterward. The lock is held during the entire execution of the method.
In your example, only one thread will be executing f() or g() at any given time because the "other" thread will be waiting its turn to grab the lock.
When you have two objects of the same class, you have two locks. That means you could get two threads to run f() and g() simultaneously with the synchronized keywords intact, as the threads will be grabbing locks on different objects. You just can't get threads to execute simultaneously on the same object without removing the synchronized keyword.
The correct answer to this is reassembler's answer.
Run this and you'll see. You can also test using Thread.sleep() instead of an infinite loop by uncommenting/commenting the according sections of the sample.
I apologize if the code doesnt follow best practices, my java is pretty rusty.
package threadtest;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ThreadTest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
TestClass tc = new TestClass();
// invokes not sync method
FirstThreadRunnable ftr = new FirstThreadRunnable(tc);
Thread t1 = new Thread(ftr);
// invokes the sync method
SecondThreadRunnable str = new SecondThreadRunnable(tc);
Thread t2 = new Thread(str);
t2.start();
t1.start();
System.in.read();
}
public static class TestClass {
private int callCount = 0;
public void notSynchronizedMethod() {
System.out.println("notSynchronizedMethod says hello!" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());
}
public synchronized void synchronizedMethod() throws InterruptedException {
// Test with the sleep
//System.out.println("entering sync method and pausing from thread: " + Thread.currentThread().getId());
//Thread.sleep(5000); // hold the monitor for 5sec
//System.out.println("exiting sync method" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());
// Test with spinning
System.out.println("MAKE IT SPIN! from thread: " + Thread.currentThread().getId());
boolean spin = true;
while(spin){
}
System.out.println("IT STOPPED SPINNING! from thread: " + Thread.currentThread().getId());
}
}
// invokes the not sync method
public static class FirstThreadRunnable implements Runnable {
TestClass tester = null;
public FirstThreadRunnable(TestClass tester){
this.tester = tester;
}
#Override
public void run() {
for(int i = 0; i < 500; i++){
tester.notSynchronizedMethod();
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
// invokes the sync method
public static class SecondThreadRunnable implements Runnable {
TestClass tester = null;
public SecondThreadRunnable(TestClass tester){
this.tester = tester;
}
#Override
public void run() {
try {
// Test with Sleep()
//for(int i = 0; i < 5; i++){
// tester.synchronizedMethod();
//}
// Test with the spinning
tester.synchronizedMethod();
} catch (InterruptedException ex) {
Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
for the interest of technicality and pedanticality, yes, both methods could be entered at the same time. one is blocked on synchronized (this), non the less, the method is entered and running, it's first statement is being executed, and the first byte code instruction is carried out.