I am using a simple program where 2 threads are defined to simply count down from 10. I have a ThreadColor class simply to be able to color the 2 threads in different colors.
package com.sherif;
public class Main {
public static void main(String[] args) {
Countdown countdown = new Countdown();
CountdownThread t1 = new CountdownThread(countdown);
t1.setName("Thread 1");
t1.start();
CountdownThread t2 = new CountdownThread(countdown);
t2.setName("Thread 2");
t2.start();
}
}
class Countdown {
private int i;
String color;
public void doCountdown() {
switch (Thread.currentThread().getName()) {
case "Thread 1":
color = ThreadColor.ANSI_BLUE;
break;
case "Thread 2":
color = ThreadColor.ANSI_RED;
break;
default:
color = ThreadColor.ANSI_CYAN;
}
synchronized (color) {
for (i = 10; i > 0; i--) {
System.out.println(color + Thread.currentThread().getName() + " i= " + i);
}
}
}
}
class CountdownThread extends Thread {
private Countdown countdown;
public CountdownThread(Countdown countdown) {
this.countdown = countdown;
}
#Override
public void run() {
this.countdown.doCountdown();
}
}
I am synchronizing the for loop that counts down to avoid interference using the color object. Although I am defining the color as an instance variable that both threads share it still creates interference.
However, when I use a different string it works just fine.
I know that I can use synchronized on (this), but I would like to understand what exactly is going on.
Your color field value is not protected by simply synchronizing on the field, because the assignment statements that change the value are not synchronized.
The only thing the synchronized block does, is ensure that both threads are not running inside the block at the same time, and that's only if the value of color is referring to the same object.
Even though thread 1 is already inside the block, doesn't stop thread 2 from changing the value of the color field.
Timeline of your code could be:
Thread 1 sets color = ThreadColor.ANSI_BLUE.
Thread 1 enters block, synchronized on ANSI_BLUE object, and starts printing.
Thread 2 sets color = ThreadColor.ANSI_RED.
Thread 2 enters block, synchronized on ANSI_RED object, and starts printing.
As you can see, they are not even synchronizing on the same object, so both can be inside the synchronized block at the same time.
Both treads continue printing in parallel.
Related
This question already has answers here:
How threads are executed in the memory?
(2 answers)
Closed 2 years ago.
This is a simplified version of the problem. Given n number of threads, each printing a constant number all the time. For example, Thread-1 should always print 1, Thread-2 should always print 2 and so on...
How to ensure, the threads are executed in order i.e. the output should be as below:
Thread-1: 1
Thread-2: 2
Thread-3: 3
.
.
.
Thread-n: n
I have a naïve solution to do it through wait()/notify() but I guess there might be a better solution than that. Perhaps, using Semaphore maybe? I don't know.
Update:
Based on the answers received, I think I was not very clear. There are some constraints:
All threads should start at once (assume we don't really have control on that)
Once all the threads start, there should be some sort of communication between the threads to execute in order.
This sequentially execution of thread can be handled beautifully using Thread.join() method. To handle it properly, you may have to create MyRunnable(or, use any name you prefer) which implements Runnable interface. Inside MyRunnable, you can inject a parent Thread, and call parent.join() at top of MyRunnable.run() method. The code is given below:
public class SequentialThreadsTest {
static class MyRunnable implements Runnable {
static int objCount; // to keep count of sequential object
private int objNum;
private Thread parent; // keep track of parent thread
MyRunnable(Thread parent) {
this.parent = parent;
this.objNum = objCount + 1;
objCount += 1;
}
#Override
public void run() {
try {
if(parent != null) {
parent.join();
}
System.out.println("Thread-" + objNum + ": " + objNum);
} catch(InterruptedException e) {
e.printStackTrace();
// do something else
} finally {
// do what you need to do when thread execution is finished
}
}
}
public static void main(String[] args) {
int n = 10;
Thread parentThread = null;
for(int i=0; i<n; i++) {
Thread thread = new Thread(new MyRunnable(parentThread));
thread.start();
parentThread = thread;
}
}
}
And the output is:
Thread-1: 1
Thread-2: 2
Thread-3: 3
Thread-4: 4
Thread-5: 5
Thread-6: 6
Thread-7: 7
Thread-8: 8
Thread-9: 9
Thread-10: 10
You haven't specified many details, but if you only want serializable thread execution you can wait for previous thread to finish and then print. Something like this:
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 10; i++) {
int index = i;
Thread previousThread = thread;
thread = new Thread(() -> {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
});
thread.start();
}
}
Try making a queue - this will do exactly what you want. Simply change the value of n to however many threads you have, and add all the threads sequentially (only once). If ever you want to stop the threads from executing, all you have to do is add end to the queue. Obviously, for a larger project, you will need to modify this code a little bit (I would recommend replacing the main method with a class initializer and pass the LinkedBlockingQueue as a pre-built argument)
import java.util.concurrent.LinkedBlockingQueue;
public class HelloWorld{
private static int n = 2;
private static LinkedBlockingQueue<Thread> queue = new LinkedBlockingQueue<>(n+1);
static Thread a = new Thread(()->{
System.out.print("a");
});
static Thread b = new Thread(()->{
System.out.print("b");
});
static Thread end = new Thread(()->{
break_ = true;
});
public static final int END = 20;//this and the counter are just here so the code doesn't run forever
public static volatile int i = 0;
public static volatile boolean break_ = false;
public static void main(String []args){
queue.add(a);
queue.add(b);
//queue.add(end);
outerloop:
while(true){
Thread toBeRun = queue.poll();
try{
toBeRun.run();
queue.add(toBeRun);
i++;
if(i>=END || break_){//i>=END does not need to be here, it's just to stop it from running forever in this example
break;
}
}catch(NullPointerException e){
break;
}
}
}
}
Note: This uses java 8 lambdas. If you're using an older version of java, you will need to create the threads using the run method.
I have a class MyClass which contains a static method GetObject(). Multiple threads are calling GetObject(). If int count is less then 3, then use old object (created in class member).
Assume Threads t4, t5, t6 enters ELSE block.
I am stuck in a ELSE condition block in which:
I want to create new Object() only once for the first thread (t4) which enters lock() (t5 and t6 are still blocked)
After unlock of first thread (t4), rest of blocked threads (t5 & t6) should return the newly created object by first thread (t4) instead of creating new Object per thread.
I do not want other blocked Threads to create new Object().
I have also tried with Condition
I have tried below code.
public Class MyClass //Singleton - persistent data class.
{
static MyClass s_instance; //Singleton instance
Object myObject = new Object();
private int count = 0;
private final Lock myLock = new ReentrantLock();
public MySystem()
{
s_instance = this;
System.out.println("Constructor finished");
}
public static Object GetObject()
{
if(s_instance.count < 3)
{
s_instance.count++;
System.out.println("FROM IF " + s_instance.myObject);
return s_instance.myObject;
}
else
{
s_instance.myLock.lock(); <----- All threads blocked here
try{
Thread.sleep(2000); //Performing database operations here.
System.out.println("Creating new Object");
s_instance.myObject = new Object(); //Assigning new Object to Singleton class.
}catch(InterruptedException ex) {
//Handling exception HERE
} finally {
s_instance.myLock.unlock();
}
System.out.println("FROM ELSE " + s_instance.myObject);
}
return s_instance.myObject;
}
}
Expected Output from logs:
FROM IF java.lang.Object#aa940f3 <--- Old object
FROM IF java.lang.Object#aa940f3 <--- Old object
FROM IF java.lang.Object#aa940f3 <--- Old object
Creating new Object
FROM ELSE java.lang.Object#64fed39d <--- Thread t4 New object
FROM ELSE java.lang.Object#64fed39d <--- Object created by Thread t4.
FROM ELSE java.lang.Object#64fed39d <--- Object created by Thread t4.
The following code from your GetObject() method is not thread safe because 2 threads could evaluate the if(s_instance.count < 3) condition simultaneously, then both of them would increment s_instance.count++, potentially causing the counter to reach a value greater than 3:
//NOTE: this is not thread safe
if(s_instance.count < 3)
{
s_instance.count++;
System.out.println("FROM IF " + s_instance.myObject);
return s_instance.myObject;
}
Additionally, since the problematic code block always returns from the GetObject() method, there is no need for an else statement. To make the GetObject() method thread safe, I suggest the following changes:
public static Object GetObject() {
do {
synchronized(s_instance) {
if(s_instance.count < 3) {
//We can safely increment here, and the return will break us out of do/while loop
s_instance.count++;
System.out.println("FROM IF " + s_instance.myObject);
return s_instance.myObject;
}
}
//Now, the only way execution reaches here is if the count reached 3
s_instance.myLock.lock();
//Because multiple threads could reach here, we only want the first one
//to create a new instance, all the others should loop
if(s_instance.count == 3) {
try {
Thread.sleep(2000); //Performing database operations here.
}
catch(InterruptedException ex) {
//Handling exception HERE
}
finally {
//Moved the logic to finally block so even if sleep was interrupted, a new instance will be constructed
System.out.println("Creating new Object");
s_instance.myObject = new Object(); //Assigning new Object to Singleton class.
s_instance.count = 0; //don't forget to reset counter
s_instance.myLock.unlock();
return s_instance.myObject; //return from here to break out of do/while loop
}
}
else {
//We weren't the first thread to want a new object, so release the
//lock and the while loop will let redo the increment logic
s_instance.myLock.unlock();
}
} while(true); //Keep looping until we are successful
}
I am pretty new to Multithreading programming. In my code threads are trying to acquire locks around few lines. The lines work pretty fine for few context switches but then it halts (probably a deadlock).
On the other hand if use synchronized block then all works fine.
I've four classes.
1. PetersonAlgorithm.java
package com.ashish.master;
public class PetersonAlgorithm {
boolean wantCS[] = {false, false};
int turn = 1;
public void requestCS(int i) {
System.out.println("Lock requested by the thread - " + i);
wantCS[i] = true;
turn = 1 - i;
while(wantCS[1-i] && turn == 1-i);
}
public void releaseCS (int i) {
wantCS[i] = false;
turn = i - 1;
System.out.println("Lock released by the thread - " + i);
}
}
If anyone feels that above algorithm is incorrect then let me know, and feel free to make suggestions.
2. Runner.java
package com.ashish.master;
public class Runner {
public static Incrementer runnableInstance = new Incrementer();
public static Thread inc1 = new Thread(runnableInstance, "0");
public static Thread inc2 = new Thread(runnableInstance, "1");
public static void main(String args[]) {
inc1.start();
inc2.start();
try{
inc1.join();
inc2.join();
} catch (InterruptedException ex) {
System.out.println("The threads have been interrupted while waiting for the join ---> " + ex.getMessage());
}
System.out.println("The total turns taken by incrementer are ----> " + runnableInstance.turns);
}
}
3. Incrementer.java - If synchronized block is used instead of the Peterson algorithm, everything works fine.
package com.ashish.master;
public class Incrementer implements Runnable {
public long turns = 0;
public PetersonAlgorithm pa = new PetersonAlgorithm();
#Override
public void run() {
System.out.println("Thread " + this.toString() + "started.....");
while(true) {
pa.requestCS(Integer.parseInt(this.toString()));
// synchronized(this) {
if(DataStore.data < 1000000) printCriticalSection();
else break;
// }
pa.releaseCS(Integer.parseInt(this.toString()));
}
}
public void printCriticalSection() {
System.out.println("The value of the number is increased by thread " +
this.toString() +" to --> " + DataStore.increase());
turns ++;
}
#Override
public String toString() {
return Thread.currentThread().getName();
}
}
4. DataStore.java A class to mock the data source -- simply increase the number
package com.ashish.master;
public class DataStore {
public static long data = 0L;
public static long increase() {
DataStore.data += 1;
return DataStore.data;
}
}
Your runnables never observe each other's monitors (wantCS and turn) as they have different instances... Each runnable needs to work with a same shared set of monitors!
Take the blue pill and make your PetersonAlgorithm variables static volatile with synchronized block access...
Or take the red pill and you create a Class for your flag monitors (wantCS) and for your indicator monitor (turn). Then just define your runnable with one "own flag", one "observed flag" and one "indicator". Both Runnables will have the same indicator instance (therefore needs to be synchronized) while the flag instances will be crossed (the own flag of R1 will be the observed flag of R2 and the own flag of R2 the observed flag of R1). You should synchronized the flag methods too as you don't want to have a flag raised or lowered while being observed.
Then few steps:
Runnables raise their Flag
Runnables turn the shared Indicator ( set to opponent runnable's id )
Wait if opponent's flag is raised and Indicator is set to opponent.
The non waiting opponent does its stuff then lowers its flag.
The waiting opponent stops waiting (opponent's flag has been lowered), does its stuff and lowers its flag.
Each of your runnable instances has its own PetersonAlgorithm instance. Thus, the two runnables don't know anything about each other and will both always get immediate access to the critical section. Try implementing your PetersonAlgorithm class as static class with static methods. Then change the lines
pa.requestCS(Integer.parseInt(this.toString()));
// ...
pa.releaseCS(Integer.parseInt(this.toString()));
into
PetersonAlgorithm.requestCS(Integer.parseInt(this.toString()));
// ...
PetersonAlgorithm.releaseCS(Integer.parseInt(this.toString()));
I have two threads doing calculation on a common variable "n", one thread increase "n" each time, another decrease "n" each time, when I am not using volatile keyword on this variable, something I cannot understand happens, sb there please help explain, the snippet is like follow:
public class TwoThreads {
private static int n = 0;
private static int called = 0;
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
n = 0;
called = 0;
TwoThreads two = new TwoThreads();
Inc inc = two.new Inc();
Dec dec = two.new Dec();
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
while (called != 2) {
//System.out.println("----");
}
System.out.println(n);
}
}
private synchronized void inc() {
n++;
called++;
}
private synchronized void dec() {
n--;
called++;
}
class Inc implements Runnable {
#Override
public void run() {
inc();
}
}
class Dec implements Runnable {
#Override
public void run() {
dec();
}
}
}
1) What I am expecting is "n=0,called=2" after execution, but chances are the main thread can be blocked in the while loop;
2) But when I uncomment this line, the program when as expected:
//System.out.println("----");
3) I know I should use "volatile" on "called", but I cannot explain why the above happens;
4) "called" is "read and load" in working memory of specific thread, but why it's not "store and write" back into main thread after "long" while loop, if it's not, why a simple "print" line can make such a difference
You have synchronized writing of data (in inc and dec), but not reading of data (in main). BOTH should be synchronized to get predictable effects. Otherwise, chances are that main never "sees" the changes done by inc and dec.
You don't know where exactly called++ will be executed, your main thread will continue to born new threads which will make mutual exclusion, I mean only one thread can make called++ in each time because methods are synchronized, and you don't know each exactly thread will be it. May be two times will performed n++ or n--, you don't know this, may be ten times will performed n++ while main thread reach your condition.
and try to read about data race
while (called != 2) {
//System.out.println("----");
}
//.. place for data race, n can be changed
System.out.println(n);
You need to synchronize access to called here:
while (called != 2) {
//System.out.println("----");
}
I sugest to add getCalled method
private synchronized int getCalled() {
return called;
}
and replace called != 2 with getCalled() != 2
If you interested in why this problem occure you can read about visibility in context of java memory model.
So I have a code:
public void runThreads(int number)
{
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < number; i++)
{
Thread t = new MyThread(getRandomPerson(),i);
threadList.add(t);
}
for (Thread x : threadList)
{
x.start();
}
}
So I am adding threads to my list of threads and then starting this threads.
This is MyThread class:
public class MyThread extends Thread
{
Person person;
int number;
public MyThread(Person person, int number)
{
this.person = person;
this.number = number;
}
#Override
public void run()
{
try
{
synchronized (this)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I wanted to make a program which creates the threads, adds them to the list, invokes them but each thread should wait until the previous ended its task.
So output should be like :
1 Surname
/** Waitning second */
1 person.toString()
/** Waiting second*/
And then the second thread start invoking:
2 Surname
....
How to achieve this using synchronized? I tried different ways to use synchronized but it failed.
public class MyThread extends Thread
{
private static Object lock = new Object();
...
synchronized (lock)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
...
That way you will get the same person's surname and toString() in order. You won't enforce strict ordering on the people, person 7 may still go before person 1.
You need a common lock - at the moment you are synchronizing on this, which is different for each thread. Try something like:
private static final Object lock = new Object();
and synchronize on that static (therefore shared) variable instead.
If you must use threads and if you must have order of execution, then you can do a t.join() immediately after t.start() - this will ensure the following flow:
- Main Thread
- loop
- start child thread
- wait for child thread to finish
- continue loop
- Exit Main thread
But, as pointed before, you don't need threads to do this since you can see that there is absolutely no gain from this approach (apart from academical) and it's detrimental in fact.
And special thanks to #assylias.