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);
}
}
}
Related
This question already has answers here:
Java Wait and Notify: IllegalMonitorStateException
(2 answers)
Closed 4 years ago.
Was trying to practice producer and consumer using a simple counter in java.
Not sure why I am getting a Illegal Monitor State exception on this piece of code.
I have counter rest and counter consume methods which run in their own thread.
The counter itself is a static int volatile field .
The counter class also gives you a lock to
If I change the wait naotify to the following:
Counter.lock.notify();
Counter.lock.wait();
The code works. Dosen't wait() and notify() automatically takes the reference of the lock synchronize is on?
Producer Class
package multithreading;
public class CounterProducer implements Runnable {
public void run() {
try { incrCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void incrCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter < 1) {
System.out.println("Counter Reset");
Counter.counter = 10;
notify();
wait();
}
}
}
}
}
Consumer Class
package multithreading;
public class CounterConsumer implements Runnable {
public void run() {
try { consumeCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void consumeCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter > 0) {
System.out.println("Consumed");
Counter.counter--;
notify();
wait();
}
}
}
}
}
The Counter
public class Counter {
public static volatile int counter;
public static final Object lock = new Object();
}
The Counter
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
The Runner
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
If I change the wait naotify to the following, the code works:
Counter.lock.notify();
Counter.lock.wait();
Every Java method is either a static method of some class or an instance method of some object. If you see a method call that does not contain an explicit class name or object reference, then it is an implicit call to a method belonging to the this object.
That is to say, notify() means the same thing as this.notify(), and wait() means this.wait().
this, refers to the CounterProducer instance when it appears in your CounterProducer.incrCounter() method, and it refers to the CounterConsumer instance when it appears in your CounterConsumer.consumeCounter() method.
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.
This question already has an answer here:
why Synchronized method allowing multiple thread to run concurrently?
(1 answer)
Closed 7 years ago.
I have a class called MyRunnable:
public class MyRunnable extends Main implements Runnable {
String name; // name of thread
Thread t;
MyRunnable (String threadname) {
name = threadname;
t = new Thread(this, name);
t.start();
}
public void run() {
try {
for (int i=0;i<100000;i++) {
extend(1);
}
} catch (InterruptedException e) {
System.out.println("Thread interrupted.");
}
System.out.println("Thread " + name + " exiting.");
}
}
and a class called Main:
public class Main {
private static List<Integer> numbers=new ArrayList<>();
public synchronized void extend (int i) throws InterruptedException {
numbers.add(i);
}
public synchronized static int getSize() {
return numbers.size();
}
public static void main(String[] args) {
MyRunnable t0=new MyRunnable("0");
MyRunnable t1=new MyRunnable("1");
MyRunnable t2=new MyRunnable("2");
try {
t0.t.join();
t1.t.join();
t2.t.join();
} catch (InterruptedException e) {
}
System.out.println(getSize());
}
}
Now I would be expecting to get 300000 as output but instead I get a random number (approx. between 250000 and 290000) even though I did use synchronized methods. I did read the oracle's documentation http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html but I can't seem to figure out why this is not working as expected. Could someone explain me why ?
Thanks in advance
Methods are synchronized to the object calling them. You need to create an object shared between each of the objects and have them synchronize on that object.
private static List<Integer> numbers=new ArrayList<>();
public synchronized void extend (int i) throws InterruptedException {
synchronize(numbers) {
numbers.add(i);
}
}
synchronized here locks on the object against which the method extend is invoked (since it is an instance method). Therefore, you're synchronizing on three different objects.
If you synchronize on the shared static list (for example), you would get the expected result.
Im new to Threads and I was wondering how could I define what two or more different Threads do in a Java program. Do i define them all in the same public void run method? If so, how do I do it? I would like the Threat t1 to invoke the increment method, t2 to invoke the decrement method and both of them to call the value method
Here's the code example:
package interference;
/**
*
* #author rodrigopeniche
*/
public class Interference implements Runnable{
/**
* #param args the command line arguments
*
*/
Counter counter1= new Counter();
class Counter{
private int c= 0;
public void increment()
{
c++;
}
public void decrement()
{
c--;
}
public int value()
{
return c;
}
}
public static void main(String[] args) {
// TODO code application logic here
Thread t1= new Thread(new Interference());
Thread t2= new Thread(new Interference());
t1.start();
t2.start();
}
#Override
public void run() {
counter1.increment();
counter1.decrement();
counter1.value();
}
}
You can set names to threads like thread1, thread2. After that, in the run method, check the name of the thread currently running and do the necessary action.
You have to add a while loop inside the run method if you need to run it longer.
public static void main(String[] args) {
Interference interference = new Interference();//create a new Interference object
Thread t1 = new Thread(interference, "thread1");//pass the runnable interference object and set the thread name
Thread t2 = new Thread(interference, "thread2");//pass the runnable interference object and set the thread name
t1.start();
t2.start();
}
#Override
public void run() {
while (true) {//to run it forever to make the difference more visual
String threadName = Thread.currentThread().getName();//get the current thread's name
if (threadName.equals("thread1")) {//if current thread is thread1, increment
counter1.increment();
} else if (threadName.equals("thread2")) {//if current thread is thread2, decrement
counter1.decrement();
}
System.out.println(counter1.value());//print the value
}
}
When you run the code, you can see count is going up and down in a random manner.
In your current code, counter1 is an instance variable of class Interference. You create 2 instances of Interference and then use them to create two Thread objects. When the threads start to run, each Thread is actually working on it's own copy of counter1. I think that may not be what you expect.
package interference;
public class Interference {
static class Counter {
private int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(new Runnable() {
public void run() {
counter.increment();
System.out.println(counter.value());
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
counter.decrement();
System.out.println(counter.value());
}
});
t1.start();
t2.start();
}
}
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());
}
}