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.
Related
I have two classes, The first one is in charge of creating threads, then those threads need to be notified from the second class
Problem: I cannot find created threads from the second class, getThreadByName() always return null, Any Idea?.
FirstClass
public class class1{
protected void createThread(String uniqueName) throws Exception {
Thread thread = new Thread(new OrderSessionsManager());
thread.setName(uniqueName);
thread.start();
}
}
OrderSessionManager
public class OrderSessionsManager implements Runnable {
public OrderSessionsManager() {
}
#Override
public void run() {
try {
wait();
}catch(Exception e) {
e.printStackTrace();
}
}
SecondClass
public class class2{
protected void notifyThread(String uniqueName) throws Exception {
Thread thread = Utils.getThreadByName(uniqueName);
thread.notify();
}
}
Utils
public class Utils{
public static Thread getThreadByName(String threadName) {
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
int noThreads = currentGroup.activeCount();
Thread[] threads = new Thread[noThreads];
currentGroup.enumerate(threads);
List<String>names = new ArrayList<String>();
for (Thread t : threads) {
String tName = t.getName().toString();
names.add(tName);
if (tName.equals(threadName)) return t;
}
return null;
}
}
There are several issues with your code:
1) It breaks Java Code Conventions: class name must start with a
capital letter
2) wait() method must be called by a thread who owns the object's monitor
so you must use something like:
synchronized (this) {
wait();
}
3) notify() method must be called by a thread who owns the object's monitor and by the same object as wait(), in your case OrderSessionsManager's instance.
4) Since you do not specify a ThreadGroup, the thread gets it's ThreadGroup from it's parent. The following code works as expected:
public class Main {
public static void main(String[] args) {
class1 c1 = new class1();
try {
c1.createThread("t1");
} catch (Exception e) {
e.printStackTrace();
}
Thread thread = Utils.getThreadByName("t1");
System.out.println("Thread name " + thread.getName());
}
}
but this happens only because the t1 thread is in the same group as the main thread.
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.
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);
}
}
}
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());
}
}
This question already has answers here:
Odd even number printing using thread
(13 answers)
Closed 8 years ago.
I am learning Java but have trouble with synchronized. i want print list of numbers from many Java threads and have each thread go in order.I get problem when using synchronized because i not much understand. Can help understand?
I want output to see this but sometimes threads in wrong order.i want:
1-thread1
2-thread2
3-thread1
4-thread2
5-thread1
6-thread2
...
48-thread2
49-thread1
My broken codes:
public class ManyThreadsAdd {
public static int index = 0;
public static void main(String[] args) {
ManyThreadsAdd myClass = new ManyThreadsAdd();
Thread thread1 = new Thread(myClass.new RunnableClass());
Thread thread2 = new Thread(myClass.new RunnableClass());
thread1.start();
thread2.start();
}
class RunnableClass implements Runnable {
public synchronized void run() {
while (index < 49) {
try {
Thread.sleep(100);
System.out.println(index+"-" +Thread.currentThread());
index = index + 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
It depends on what you want to do.
A simple way to alternate the order of the print is to synchronize on the same object, in this case you can use the index or any other object.
public class ManyThreadsAdd {
public static AtomicInteger index = new AtomicInteger(0);
public static void main(String[] args) {
ManyThreadsAdd myClass = new ManyThreadsAdd();
Thread thread1 = new Thread(myClass.new RunnableClass());
Thread thread2 = new Thread(myClass.new RunnableClass());
thread1.start();
thread2.start();
}
class RunnableClass implements Runnable {
public void run(){
synchronized(index){
while(index.get() < 49){
try {
Thread.sleep(100);
System.out.println(index.get()+"-" +Thread.currentThread());
index.incrementAndGet();
index.notify();
index.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
Firstly, multithreading by nature is asynchronous, you cannot specify the order in which these threads get executed. If you want output like below, use a loop:
1-thread1
2-thread2
3-thread1
4-thread2
5-thread1
6-thread2
...
48-thread2
49-thread1
Secondly, you gain nothing by adding the synchronized keyword in public synchronized void run(). This just means that at any time, only one thread at a time can call that method. As you are constructing new classes for each thread, this is meaningless.
Thirdly, if you did need to synchronise between your threads, use a queue to which you add tasks, and which your threads read one at a time.