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);
}
}
Related
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.
I am new to threads in Java and hence have this doubt. I read that a 'synchronized non-static method block' allows only one thread to enter the block (for one instance of non-static block, of-course). However it doesn't seem to work. Am I missing something?
Look at the following code.
class A extends Thread
{
public void run()
{
B.b.add();
}
}
class B
{
static B b=new B();
int i;
public synchronized void add()
{
i++;
}
}
public class Sample
{
public static void main(String[] args)
{
for(int i=0;i<10;i++)
{
new A().start();
}
System.out.println(B.b.i);
}
}
One problem here is that your main thread doesn't wait for the other threads to finish before it tries to retrieve the result. Using Thread#join works if you want to wait for a single thread, but here we want to wait for all 10. Modifying the program to use CountDownLatch makes the main thread wait until all the threads it created are finished.
Another problem is that the updated value of i isn't guaranteed to be visible. JVM implementations differ about how aggressively they perform optimizations (like delaying refreshes of cached values, or reordering bytecode) that may make the changes to i not visible to the main thread. Adding a synchronized method on the same lock as the add method to fetch the value of i fixes the visibility issue.
import java.util.concurrent.CountDownLatch;
class A extends Thread {
private CountDownLatch latch;
public A(CountDownLatch latch) {
this.latch = latch;
}
#Override public void run() {
B.b.add();
latch.countDown();
}
}
class B {
static B b=new B();
int i;
public synchronized void add() {
i++;
}
public synchronized int getI() {
return i;
}
}
public class Sample {
public static void main(String[] args) throws Exception {
CountDownLatch latch = new CountDownLatch(10);
for(int i=0;i<10;i++) {
new A(latch).start();
}
latch.await();
System.out.println(B.b.getI());
}
}
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 have a static function like:
public static void foo()
{
//code follows
System.out.println(Thread.currentThread().getName());
//code follows
}
and multiple threads are calling this function concurrently. I have set the names of threads using
Thread.setName(String)
When i execute the code, the print statement will print the name of only one thread. How can i identify the names of all the threads currently executing the foo() function?
EDIT:
public class FooThread extends Thread
{
public FooThread(String name)
{
this.setName(name);
}
#Override public void run()
{
//do something
//do something
Main.foo();
}
}
//Main Class
public class Main
{
public static void main(String[] args)
{
for(int i=0;i<6;++i)
{
new FooThread("Thread"+i).start();
}
}
public static void foo()
{
//do something
while(true)
{
//do something
System.out.println(Thread.currentThread().getName());
}
}
}
You're already showing the name of the Thread that is calling your code. Code that proves this:
public class Foo2 {
public static synchronized void foo() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
int maxCount = 10;
for (int i = 0; i < maxCount; i++) {
Thread thread = new Thread(new Runnable() {
public void run() {
foo();
}
});
thread.setName("Thread " + i);
thread.start();
long sleepTime = 1000;;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
}
}
Return:
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
Thread 7
Thread 8
Thread 9
Your problem lies in code not shown.
Either your method is being called by one and only one thread, or
Or you're giving all your threads the same name.
Again, for a complete solution as to what is actually wrong with your current set up, create and post an sscce similar to what I've posted above. For all we know you could be calling run() on your Threads, and until we can see and reproduce your problem, I don't think that we'll be able to fully understand it.
EDIT
Regarding your SSCCE: Compare the results of the two methods below, foo1() and foo2()
class FooThread extends Thread {
public FooThread(String name) {
this.setName(name);
}
#Override
public void run() {
// do something
// do something
Main.foo1(); // !! Swap comments
// Main.foo2(); // !! Swap comments
}
}
// Main Class
public class Main {
private static final long SLEEP_TIME = 4;
public static void main(String[] args) {
for (int i = 0; i < 6; ++i) {
new FooThread("Thread" + i).start();
}
}
public static void foo1() {
// do something
while (true) {
// do something
synchronized (Main.class) {
System.out.println(Thread.currentThread().getName());
}
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
}
public static void foo2() {
while (true) {
System.out.println(Thread.currentThread().getName());
}
}
}
If your while loop isn't so tight, but yields the CPU with say a short Thread.sleep, you'll see more of the different threads sharing foo in closer proximity.
But again, your code also proves that your Thread names *are8 being displayed, but that you're only seeing one name likely because that thread is hogging the CPU.
Another option is to get all the Thread stacks and look for all the threads in the foo() This has the benefit of no overhead or extra code, except to capture the information you want.
BTW: Can you make it clearer why do you need this information as I suspect there is a better way to do what you really want?
If you only want to get the count of threads, use a thread-safe counter to store number of threads. Increase the counter when foo() begins, and decrease the counter when foo() exits.
If you need to get the names, use a hash set (or list if there are duplicates of thread names) to store the names: Add the name when foo() begins, and remove the name when foo() exits. Make sure the access to hash set is thread safe. You also need another method to print out the content of the hash set, so you can call it any time to see what are the name of threads executing foo().
You can put the name into a list when the method starts (in a synchronized block) and remove it at the end again.
List allTheNames = Collections.synchronizedList(new ArrayList<String>());
public void foo() {
allTheNames.add(Thread.currentThread().getName());
// now allTheNames contains all the names of all threads currently in this method.
System.out.println(allTheNames.toString());
allTheNames.remove(Thread.currentThread().getName());
}
Of course, if you change the name of the thread in the meantime that wont work, but why would you do so?
You could also store the Thread itself if you need other informations that the name.
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]].