I am currently learning the use of monitor in Java, but i do not know how the synchronized methods work.
I understand that while one thread is inside a synchronized method, another thread cannot be inside a synchronized method and that sleep doesn't take off the monitor's own ownership.
So i tried to write a code to test that
import java.util.Random;
public class ex3 extends Thread {
private static int nbA=0;
private static int nbB=0;
public static final Random rand = new Random();
public void run(){
while(true){
System.out.println(nbA+" "+nbB);
try{
Thread.sleep(rand.nextInt(500));
}catch (Exception e ){e.printStackTrace();}
if (rand.nextBoolean()){
try {
A();
} catch (InterruptedException e) {}
}else{
try {
B();
} catch (InterruptedException e) {}
}
}
}
public synchronized void A() throws InterruptedException{
nbA++;
Thread.sleep(rand.nextInt(500));
nbA--;
}
public synchronized void B() throws InterruptedException{
nbB++;
Thread.sleep(rand.nextInt(500));
nbB--;
}
public static void main(String[] argv){
new ex3().start();
new ex3().start();
new ex3().start();
}
}
I believed it was impossible that nbA or nbB be superior to 1 or that nbB and nbA are both >0 but it's happening
What do I misunderstand ?
Sorry for the bad english.
You're synchronizing on different objects: a synchronized non-static method synchronizes on this, so each of the new ex3() instances effectively works like it's not synchronized.
A synchronized instance method is exactly equivalent to this:
public void A() {
synchronized (this) {
// The body.
}
}
Either make the synchronized methods static, or explicitly synchronize on the class (or something other shared object):
public void A() throws InterruptedException{
synchronized (ex3.class) {
nbA++;
Thread.sleep(rand.nextInt(500));
nbA--;
}
}
I understand that while one thread is inside a synchronized method, another thread cannot be inside a synchronized method
Wrong. It cannot be inside a synchronized method synchronized on the same object. It can be inside any other synchronized method, or the same method synchronized on a different object, as here.
and that sleep doesn't take off the monitor's own ownership.
Correct.
NB Per Brinch Hansen doesn't consider Java to have monitors, and he invented them.
Related
Here is my code
class Thread1 extends Thread
{
public synchronized void show()
{
System.out.println("show");
System.out.println(Thread.currentThread().getName());
try
{
Thread.sleep(5000);
}
catch(Exception e)
{
System.out.println(e);
}
}
public synchronized void display()
{
System.out.println("Display");
System.out.println(Thread.currentThread().getName());
}
public static void main(String args[])
{
Thread1 z=new Thread1();
z.set();
}
public void set()
{
Thread1 tr=new Thread1();
Thread1 tr1=new Thread1();
tr.start();
tr1.start();
}
public void run()
{
try
{
show();
display();
}
catch(Exception e)
{
System.out.println(e);
}
}
}
I assume you meant to ask about why show is printed by both threads before either of the thread names are printed.
You are synchronizing your instance methods, so they are implicitly locking on the object on which the method is called. However, you have 2 different Thread1 objects locking on themselves, so neither thread is stopping the other from entering the synchronized methods.
If you intend to have only one Thread execute each of the synchronized methods at a time, then you need to lock on a common object. Use a synchronized block that locks on Thread1.class.
Here is what that looks like for the show method.
public void show()
{
synchronized (Thread1.class)
{
System.out.println("show");
System.out.println(Thread.currentThread().getName());
try
{
Thread.sleep(5000);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
The display method can be modified similarly.
You are instantiating two different objects that have their own state (tr and tr1). They never access the same synchronised block, and thus never block waiting for the other one to finish.
Try moving the show method to another class, instantiate that class and then pass it to tr and tr1 as a constructor parameter, for example.
From the tutorial I read:
it is not possible for two invocations of synchronized methods on the
same object to interleave. When one thread is executing a synchronized
method for an object, all other threads that invoke synchronized
methods for the same object block (suspend execution) until the first
thread is done with the object.
However, in my simple example there is still a race competition to access the message object.
public class TestThread extends Thread{
int thread;
StringBuilder message;
public TestThread(int thread, StringBuilder message) {
this.thread=thread;
this.message=message;
start();
}
public void run() {
synchronized(this){
for (int i=0; i<1000000; i++) {
double a=2*2;
}
modifyMessage();
}
}
public synchronized void modifyMessage() {
message.append(thread);
}
}
public class TestMultithreading {
static TestThread[] testThreads = new TestThread[5];
public static void main(String args[]) {
StringBuilder message = new StringBuilder("A");
for (int i=0;i<5;i++)
testThreads[i] = new TestThread(i, message);
for (int i=0;i<5;i++)
try {
testThreads[i].join();
} catch (InterruptedException e) {}
out.println(message);
}
}
I expect this to have a guaranteed output of a string of length 6. However, from time to time I see something like this:
A1034
This means that one of the threads failed to modify the object. Can someone explain me, why this happens and propose a solution for the problem?
You already answered your own question:
When one thread is executing a synchronized method for an object, all
other threads that invoke synchronized methods for the same object
block
The synchronized only block access on the method of the same object, which means that in every thread the modifyMessage() can be called at the same time
What you are looking for is a something like this:
for (int i=0; i<1000000; i++) {
double a=2*2;
}
synchronized(message){
modifyMessage();
}
Now the method is only call once per StringBuilder instance.
Your methods are all synchronizing on a different object (this).
If you change the method to synchronize on a single object, it'll work. For example.
public void modifyMessage() {
synchronized(message) {
message.append(thread);
}
}
I have two Java classes as below...
(1) JavaClass SyncTest: It defines a class (implementing Runnable) and invokes a "synchronized" method (named "call") defined in Class SyncTestCalled
(2) JavaClass SyncTestCalled : There is one synchronized method.
------
After calling from main(), I am thinking it should output something like:
[Two]
[Three]
[One]
But, it outputs something like this (note the open bracket which is not paired in right locations) :
[[[Two]
Three]
One]
What's wrong with the codes? Please help. Thanks a lot!
Here is the code of these two classes...
public class SyncTest implements Runnable {
Thread t;
String name;
SyncTestCalled syncTestCalled;
public SyncTest(String name) {
t = new Thread(this, name);
syncTestCalled = new SyncTestCalled();
this.name = name;
t.start();
}
public void run() {
syncTestCalled.call(this.name);
}
public static void main(String[] args) {
SyncTest syncTest1 = new SyncTest("One");
SyncTest syncTest2 = new SyncTest("Two");
SyncTest syncTest3 = new SyncTest("Three");
}
} // of class SyncTest
public class SyncTestCalled {
public SyncTestCalled() {
// Do nothing
}
synchronized public void call(String message) {
System.out.print("[");
try {
Thread.sleep(1000);
System.out.print(message);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("]");
}
} // of class SyncTestCalled
When you use synchronized as part of the method declaration, Java attempts to acquire the monitor (lock) on the object the method is invoked on. So a method like
synchronized public void call(String message) {
...
}
is equivalent to
public void call(String message) {
synchronized (this) {
...
}
}
In your code, you create three different SyncTestCalled objects and pass each individual one to the different SyncTest instances. In other words, nothing is coordinated. Each call to
syncTestCalled.call(this.name);
is synchronized on a different object and therefore none of the threads need to wait on the others.
It's up to the Thread scheduler who gets where first, so you get output like
[[[Two]
Three]
One]
or
[[[OneThree]
Two]
]
Note that Thread.sleep(long) does not relinquish any monitors the thread currently has.
Only one thread can invoke your call() method on a given instance at any given time. But what you want is atomicity for several calls to System.out.print() methods. For that, you need to acquire a lock on System.out instead:
synchronized (System.out) {
System.out.print('[');
System.out.print(message);
System.out.println(']');
}
Because PrintStream locks on itself, this will prevent other threads from interleaving their own calls to print().
i was working with the synchronized statement and made the following program...synchronized the runn class with this as object reference ..bt smhw the desired output is nt there....
class runn extends Thread {
String s;
runn(String a) {
s=a;
start();
}
public void show() {
System.out.print("["+s);
try {
sleep(50);
} catch(Exception a){}
System.out.print("]");
}
public void run() {
synchronized(this) {
show();
}
}
}
public class multi4 {
public static void main(String[] args) throws InterruptedException{
new runn("hello ");
new runn("this is ");
new runn("multithreading");
}
}
The output should be :
[hello][this is][multithreading]
but synchronisation is not working smhw
Please help.
Two mistakes:
You synchronized on the individual runn objects. This has no effect because each thread uses a different synchronization object.
The synchronized keyword does not magically cause threads to run in order. It merely prevents threads from attempting to execute the synchronized block at the same time, if you synchronize on the same object. They may still run in any order, but wouldn't be able to interleave their output. That is, if you synchronized on a shared object, you could get e.g. [this is][hello][multithreading], but not [this is[hello][multithreading]].
I have some code that I want to have some one time initialisation performed. But this code doesn't have a definite lifecycle, so my logic can be potentially invoked by multiple threads before my initialisation is done. So, I want to basically ensure that my logic code "waits" until initialisation is done.
This is my first cut.
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
synchronized(initialised) {
initStuff();
initialised.getAndSet(true);
initialised.notifyAll();
}
}
public void doStuff() {
synchronized(initialised) {
if (!initialised.get()) {
try {
initialised.wait();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
}
}
doOtherStuff();
}
}
I basically want to make sure this is going to do what I think it's going to do -- block doStuff until the initialised is true, and that I'm not missing a race condition where doStuff might get stuck on a Object.wait() that will never arrive.
Edit:
I have no control over the threads. And I want to be able to control when all of the initialisation is done, which is why doStuff() can't call initialise().
I used an AtomicBoolean as it was a combination of a value holder, and an object I could synchronize. I could have also simply had a "public static final Object lock = new Object();" and a simple boolean flag. AtomicBoolean conveniently gave me both. A Boolean can not be modified.
The CountDownLatch is exactly what I was looking for. I also considered using a Sempahore with 0 permits. But the CountDownLatch is perfect for just this task.
That's a strange mix of library and built-in concurrency controls. Something like this is much cleaner:
public class MyClass {
private static final CountDownLatch latch = new CountDownLatch(1);
public void initialise() {
initStuff();
latch.countDown();
}
public void doStuff() {
try {
latch.await();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
doOtherStuff();
}
}
A synchronized block will automatically block other threads. Just use a simple lock object + status variable:
public class MyClass {
private static boolean initialised;
private static final Object lockObject = new Object();
public void initialise() {
synchronized (lockObject) {
if (!initialised) {
initStuff();
initialised = true;
}
}
}
public void doStuff() {
initialise();
doOtherStuff();
}
}
The best may be to use a static initializer (as mentioned by SB):
public class MyClass {
public static void doInitialize() {
...
}
public void doStuff() {
doOtherStuff();
}
static {
doInitialize();
}
}
This will get executed once before any other code is allowed to be called. If you will always have to initialize anytime the class is used then there is no performance hit as the class will not be loaded until it is used. See the answers to this question for more details.
It this is right at startup, why not wait to start the other threads until the initialization is complete?
Also, you can do a thread-synchronized IsComplete boolean that is set to false until it is set to true by the initialization routine.
You're using AtomicBoolean always from inside a synchronized block. There's not much point to that since only one thread can access it. Atomic variables are intended for use in lock-free solutions - you can get and set the value as an uninterruptable unit.
I guess you are looking for a lock free solution once the intiialization has happened:
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
if (!intialized.get())
{
synchornized (this)
{
if (!initialized.getAndSet(true))
doInitialize();
}
}
}
public void doStuff() {
initialize();
doOtherStuff();
}
You could also do this with a simple volatile boolean which is actually a little more efficient than an AtomicBoolean.