I looked around and seemed similar code but mine is not working. My volatile variable is chaning in the class clock but my class vistor is not getting the changed variable. I will post my code. If theres a similar queston please link. Thank you for the help.
I tried by setting the declarations in all my classes for the volatile boolean variables to false. It didn't help.
public class Main {
volatile static boolean isInSession;
volatile static boolean sessionOver;
public static void main (String [] args)
{
for (int i = 0; i < 25; i++) {
Visitor visitor = new Visitor(i, isInSession);
visitor.start();
}
Thread clock = new Thread(new Clock(isInSession, sessionOver));
clock.start();
}
}
public class Visitor extends Thread {
volatile static boolean isInSession;
private int visitorId;
volatile static int seats = 5;
Visitor(int visotrId, boolean isInSession)
{
this.isInSession = isInSession;
setName("visitorId " + visitorId);
}
#Override
public void run() {
while(true)
{
while(isInSession){}
System.out.println("In visitor isInSession " + isInSession);
if(isInSession)
System.out.println("Visitor isInSession " + isInSession);
try {
Thread.currentThread().sleep(5000);
}
catch(InterruptedException e)
{ }
}
}
public void msg(String m) {
System.out.println("["+(System.currentTimeMillis()-time)+"]
"+getName()+": "+m);
}
}
public class Clock implements Runnable {
volatile static boolean isInSession;
volatile static boolean sessionOver;
private int session = 0;
public Clock(boolean isInSession, boolean sessionOver)
{
this.isInSession = isInSession;
this.sessionOver = sessionOver;
}
#Override
public void run() {
while(true)
{
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
}
isInSession = false;
msg("Theater is open");
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
}
isInSession = true;
//System.out.println("In clock isInSession " + isInSession);
session++;
}
}// end of run
public void msg(String m) {
System.out.println("["+(System.currentTimeMillis()-time)+"]" +"Clock:
"+ m);
}
}
You can use AtomicBoolean for your purpose.
As JB Nizet has pointed out, arguments in Java are passed-by-value. Here's an answer on another SO post that explains this in detail.
For your purpose, it suffices to know that, "when we pass the value of an object, we are passing the reference to it" (a quote from the SO post mentioned above). By creating an AtomicBoolean object and passing it to both the Clock and Visitor objects, when Clock updates the value of the AtomicBoolean, the Visitor objects will receive the updated value too.
So, your main class should look like this:
public class Main {
static AtomicBoolean isInSession = new AtomicBoolean(); // default value is false
static AtomicBoolean sessionOver = new AtomicBoolean();
public static void main (String [] args)
{
for (int i = 0; i < 25; i++) {
Visitor visitor = new Visitor(i, isInSession);
visitor.start();
}
Thread clock = new Thread(new Clock(isInSession, sessionOver));
clock.start();
}
}
To access the value of the AtomicBoolean in Visitor or to update the value in Clock, you can use the get() and set(boolean) method respectively.
Related
From the link, it provide a demo of the java keyword 'volatile'. The demo code works fine. But I try to do a little modification. the behaviour is defferent.
My code :
public class VolatileTest4 {
private static int MY_INT = 0;
public static void main(String[] args) {
new ChangeListener().start();
new ChangeMaker().start();
}
static class ChangeListener extends Thread {
#Override
public void run() {
while (MY_INT < 5) {
System.out.println("Got Change for MY_INT : " + MY_INT);
}
}
}
static class ChangeMaker extends Thread {
#Override
public void run() {
while (MY_INT < 5) {
System.out.println("Incrementing MY_INT to " + MY_INT);
MY_INT++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
What I do is just remove the local variable of local_value.
The post says 'Without the volatile keyword, the change listener loop infinitely'.
But My code is Without the volatile keyword, the change listener ends normally.
What is the defference? what cause the change listener end?
I've compared the code you've provided to the code in the article and there are substantive differences. Having modified and run the code from the article in the manner described by the author, I was able to replicate his results. My code is as follows:
public class VolatileTest {
private static int MY_INT = 0;
public static void main(String[] args) {
new ChangeListener().start();
new ChangeMaker().start();
}
static class ChangeListener extends Thread {
#Override
public void run() {
int local_value = MY_INT;
while ( local_value < 5){
if( local_value!= MY_INT){
System.out.println(String.format("Got Change for MY_INT : %S", MY_INT));
local_value= MY_INT;
}
}
}
}
static class ChangeMaker extends Thread{
#Override
public void run() {
int local_value = MY_INT;
while (MY_INT <5){
System.out.println(String.format("Incrementing MY_INT to %S", local_value+1));
MY_INT = ++local_value;
try {
Thread.sleep(500);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}
The volatile keyword changes a variable's visibility semantics. Changes to a member marked volatile become visible to all threads after the write operation completes. However, the absence of volatile doesn't mean that the changes won't be visible. volatile provides some certainty around visibility; without it, you can't be sure when changes made to a value will become visible in other threads, if ever.
The author is trying to make the point that because the variable is not marked volatile the changes made by the ChangeMaker are not visible to the ChangeReader and in turn, the ChangeListener never terminates. See this article for a better treatment of the volatile keyword.
class hehe implements Runnable {
static int count = 0;
public synchronized void count() {
count++;
}
public void run() {
for (int i = 0; i < 10000; i++) {
count();
}
}
}
public class Sychronise {
public static void main(String[] args) {
Thread a1 = new Thread(new hehe());
Thread a2 = new Thread(new hehe());
a1.start();
a2.start();
try {
a1.join();
a2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(hehe.count);
}
}
The count should be 20000, but my output is still unstable.
Currently, your synchronized does nothing as it's synchronizing on each individual 'hehe' instance. To make it synchronize on the Class object (which owns the 'count' variable) make your count method static too:
public static synchronized void count(){
count++;
}
Or synchronize on an object:
public class hehe implements Runnable {
static int count= 0;
static Object lock = new Object();
public void count(){
synchronized(lock) {
count++;
}
}
public void run(){
for (int i=0;i<10000;i++){
count();
}
}
}
The issue here is that your count method is synchronized but there are 2 instances of the object Hehe, so each synchronization would be scoped to each instance, in this case I would suggest to use an AtomicInteger
First try with a static count method.
public static synchronized void count(){
count++;
}
public void run(){
for (int i=0;i<10000;i++){
Hehe.count();
}
}
I have two threads and in one thread I set static variable and in another I check static variable via function like this
Test test= new Test();
while(!Temp.isVarSet()){
}
System.out.println("Variable set");
But this codes hangs - doesn't go to println statement. But the following code works
Test test= new Test();
while(!Temp.isVarSet()){
System.out.println("I am still here");
}
System.out.println("Variable set");
The Temp class
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public synchronized static boolean isVarSet() {
return Temp.varSet;
}
}
Test class
public class Test{
public Test() {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Model model= new Model();
View view = new View();
Controller controller=new Controller(model, view);
Temp.setVarSet();
...
}
});
}
}
What can be reason? I set method isVarSet() synchronized but it didn't help.
EDIT
This code works too.
Test test = Test()
while(!Temp.isVarSet()){
Thread.sleep(100);
}
You didn't publish what happens in Temp and isVarSet but most probably you change a variable. This variable must be marked volatile.
If your class looks like this:
public class Temp {
private static boolean someFlag;
public static boolean isVarSet() {
return someFlag;
}
}
And your loop is the same as the example, the compiler thinks that there's no need to read the flag over and over again because the flag is not changed inside the loop and it optimizes to not read the flag over and over.
Marking someFlag as volatile:
private static volatile boolean someFlag;
Will force the runtime to check the flag on each iteration and not just assume that the value hasn't changed. In this case, it will work.
From Oracle docs about atomic access:
Atomic actions cannot be interleaved, so they can be used without fear
of thread interference. However, this does not eliminate all need to
synchronize atomic actions, because memory consistency errors are
still possible. Using volatile variables reduces the risk of memory
consistency errors, because any write to a volatile variable
establishes a happens-before relationship with subsequent reads of
that same variable. This means that changes to a volatile variable are
always visible to other threads. What's more, it also means that when
a thread reads a volatile variable, it sees not just the latest change
to the volatile, but also the side effects of the code that led up the
change.
Even after you made variable as volatile .
if you add SOP in while loop it is working
These two usecase gives me another thought. just try it.
Since your read and write methods are sync , in your while loop
while(!Temp.isVarSet()){
}
It is nothing doing other than calling the method, it may possible this sync method holds the lock on the Temp Object which does not allow other thread to modify the values (though sync setMethod) .
While add SOP inside the while , it is doing some work on IO and thus it is allowing some time slice to other thread get the lock of Temp and modify the same.
Could you please try remove Sync from read method , just for testing purpose and post your results.
public class Temp {
private volatile static boolean varSet=false;
public synchronized static void setVarSet() {
Temp.varSet=true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
This works perfect for me:
public class ThreadTest {
public static void main(String[] args) throws Exception {
Thread t1 = new TheThread();
t1.start();
// wait
Thread.sleep(500);
System.out.println(Thread.currentThread().getId() + " will now setVarSet()");
Temp.setVarSet();
System.out.println(Thread.currentThread().getId() + " setVarSet() setted");
t1.join();
System.out.println(Thread.currentThread().getId() + " end programm");
}
private static class TheThread extends Thread {
#Override
public void run() {
System.out.println(Thread.currentThread().getId() + " enter run");
while (!Temp.isVarSet()) {
System.out.println(Thread.currentThread().getId() + " running");
try {
Thread.sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
// ignore
}
}
System.out.println(Thread.currentThread().getId() + " exit run");
}
}
private static class Temp {
private volatile static boolean varSet = false;
public static void setVarSet() {
Temp.varSet = true;
}
public static boolean isVarSet() {
return Temp.varSet;
}
}
}
Can you please post a complete example?
Its working as expected without hanging the program.
private volatile static boolean varSet = false;
public synchronized static void setVarSet() {
varSet = true;
}
public synchronized static boolean isVarSet() {
return varSet;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
while (!TestDemo.isVarSet()) {
// System.out.println("I am still here");
}
System.out.println("Variable set");
}
});
t1.start();
Thread.sleep(1000); // put delay to give the chance to execute above thread
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Model model= new Model();
// View view = new View();
// Controller controller=new Controller(model, view);
setVarSet();
}
});
}
I have two methods in two different classes, like this
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
System.out.println("This is A and B ");
}
}
#Override
public void run() {
methodAandB();
}
}
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
System.out.println("This is A or B");
}
}
#Override
public void run() {
methodAorB(a);
}
}
Thread t1 is calling methodAandB().
Thread t2 is calling methodAorB().
Can I switch between these two threads after each iteration of loop in methods?
I want to get output like this:
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
This is A and B
This is A or B
Best example of flip-flop between threads:
Given two int array (even and odd), 2 threads printing their numbers in natural order.
package com.rough;
public class ThreadsBehaviour {
static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
int a[] = {1,3,5,7,9};
int b[] = {2,4,6,8,10};
Thread odd = new Thread(new Looper(a, lock));
Thread even = new Thread(new Looper(b, lock));
odd.start();
even.start();
}
}
class Looper implements Runnable
{
int a[];
Object lock;
public Looper(int a[], Object lock)
{
this.a = a;
this.lock = lock;
}
#Override
public void run() {
for(int i = 0; i < a.length; i++)
{
synchronized(lock)
{
System.out.print(a[i]);
try
{
lock.notify();
if(i == (a.length - 1))
{
break;
}
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
You can achieve this simply by using the shared variables. I have implemented and verified the problem. code is below
class X
public class ClassX implements Runnable {
public void methodAandB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassXdone)
{}
System.out.println("This is A and B ");
GlobalClass.isClassXdone = true;
GlobalClass.isClassYdone = false;
}}
#Override
public void run() {
methodAandB(); } }
ClassY
public class ClassY implements Runnable {
public void methodAorB() {
for(int i=0;i<10;i++) {
while(GlobalClass.isClassYdone)
{}
System.out.println("This is A or B ");
GlobalClass.isClassYdone = true;
GlobalClass.isClassXdone = false;}}
#Override
public void run() {
methodAorB();}}
Definition of the shared variable
public class GlobalClass {
public static boolean isClassXdone = false ;
public static boolean isClassYdone = false ;
}
You can just start your thread using t1.start and t2.start to get the desired output
Thread t1 = new Thread(new ClassX());
Thread t2 = new Thread(new ClassY());
t1.start();
t2.start();
This is probably more than needed to solve the problem, but, as it seems to be an introduction to concurrent programming exercise, it should be along the lines of what you'll encounter.
You should probably have a shared object that both your threads know, so that they may synchronize through it. Like so:
public class MyMutex {
private int whoGoes;
private int howMany;
public MyMutex(int first, int max) {
whoGoes = first;
howMany = max;
}
public synchronized int getWhoGoes() { return whoGoes; }
public synchronized void switchTurns() {
whoGoes = (whoGoes + 1) % howMany;
notifyAll();
}
public synchronized void waitForMyTurn(int id) throws
InterruptedException {
while (whoGoes != id) { wait(); }
}
}
Now, your classes should receive their respective identifier, and this shared object.
public class ClassX implements Runnable {
private final int MY_ID;
private final MyMutex MUTEX;
public ClassX(int id, MyMutex mutex) {
MY_ID = id;
MUTEX = mutex;
}
public void methodAandB() {
for(int i = 0; i < 10; i++) {
try {
MUTEX.waitForMyTurn(MY_ID);
System.out.println("This is A and B ");
MUTEX.switchTurns();
} catch (InterruptedException ex) {
// Handle it...
}
}
}
#Override
public void run() { methodAandB(); }
}
ClassY should do the same. Wait for its turn, do its action, and then yield the turn to the other.
I know it's a little late to answer this. But it's yesterday only I have come across this question. So I guess it's never too late.. ;)
Solution, as #afsantos mentioned is having a shared object between the two threads and implementing mutual exclusion on the shared object. The shared object could be alternatively locked by the two threads. Two possible implementations are as follows. This is actually more like an extension of #afsantos solution. His work is hereby acknowledged.
Solution 1:
Blueprint of the object that will be shared is as follows.
public class MutEx {
public int whoGoes, howMany;
public MutEx(int whoGoes, int howMany) {
this.whoGoes = whoGoes;
this.howMany = howMany;
}
public synchronized void switchTurns(){
this.whoGoes = (this.whoGoes + 1) % 2;
notifyAll();
}
public synchronized void waitForTurn(int id) throws InterruptedException{
while(this.whoGoes != id)
wait();
}
}
Then, you could implement the ClassX as follows.
public class ClassX implements Runnable {
private final int MY_ID;
private final MutEx MUT_EX;
public ThreadOne(int MY_ID, MutEx MUT_EX) {
this.MY_ID = MY_ID;
this.MUT_EX = MUT_EX;
}
#Override
public void run(){
this.doTheWork();
}
public void doTheWork(){
for(int i = 0; i < 10; i++){
try {
MUT_EX.waitForMyTurn(MY_ID);
System.out.println("This is A and B");
MUT_EX.switchTurns();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ClassY also will be the same, with whatever the differences you need to be there. Then, in the invocation (i.e. in the main method),
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
Thread t1 = new Thread(new ClassX(0, mutEx);
Thread t2 = new Thread(new ClassY(1, mutEx));
t1.start();
t2.start();
}
Voila! You have two threads, alternating between each as you need.
Solution 2: Alternatively, you could implement the ClassX & ClassY as follows.
public class ClassX extends Thread{
Here, you are subclassing the java.lang.Thread to implement your requirement. For this to be invoked, change the main method as follows.
public static void main(String[] args) {
MutEx mutEx = new MutEx(0, 2);
ClassX t1 = new ClassX(0, mutEx);
ClassY t2 = new ClassY(1, mutEx);
t1.start();
t2.start();
}
Run this, and you have the same result.
If you don't need to use Thread try this code:
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
methodAandB();
} else {
methodAorB();
}
}
For each creation of the object, I want it to be uniquely accessible by an identifier. I am using an incrementing static value to keep track of how many objects have been created, and every time a new one is constructed, I make its identifier equivalent to count + 1 (and increment the count). The problem I am encountering is that synchronization is not working. Here is a simplified version of the code:
public static final Hashtable MODULES = new Hashtable();
private static final Object countLock = new Object();
private static int count = 0;
private final String identifier;
private final String name;
public Class(String name) {
this.identifier = String.valueOf(incrementCount());
this.name = name;
MODULES.put(identifier, name);
}
private static int incrementCount() {
synchronized (countLock) {
return ++count;
}
}
Now when I test with this (unrealistically, admittedly, but to be sure that it works):
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Class m = new Class("Name");
}
}).start();
}
System.out.println(Module.MODULES.size());
I get output anywhere from the 60's to 100. Obviously I don't want that sort of unreliability. Would a volatile field work here? (I have tried with the same results) I am not sure how to make sure every class object has a different identifier. Any solutions are welcome.
Note: I do not access to java.util.concurrent for implementation specific reasons.
Your lock is working fine but the problem is something different. You are initializing the each object through a new Thread. While the threads are running in background, the main thread, prints the count at moment. Put an appropriate delay in between, you will see the proper count.
public static void main(String[] args) throws InterruptedException{
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Counter m = new Counter("Name");
}
}).start();
}
Thread.sleep(1000);//put a delay
System.out.println(MODULES.size());
}
Try this:
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Class m = new Class("Name");
}
}).start();
}
Thread.sleep(500);
System.out.println(Module.MODULES.size());
You are printing the size of hashtable which is not synchronized.
add a synchronized statement before the statement MODULES.put(identifier, name);
synchronized (MODULES) {
MODULES.put(identifier, name);
}
it works for me.
Here is what I see as a problem in your code: The statement Class m = new Class("Name"); is in the run() function, and not in the constructor of Runnable's implementation in your code.
If I have to write a similar code, I would write it this way:
public class ModuleTest {
public static void main(String[] args) {
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
{
Module m = new Module("Name");
}
#Override
public void run() {
// do something
}
}).start();
}
System.out.println(Module.MODULES.size());
}
}
Look at the placement of statement Module m = new Module("Name"); above. It is not in run() function, as run() is called when start() is called. That statement is between unnamed braces {} that is called during construction of the anonymous implementation of Runnable you have in your code.
And to complete the above code, here is the Module class:
import java.util.Hashtable;
public class Module {
public static final Hashtable MODULES = new Hashtable();
private static final Object countLock = new Object();
private static int count = 0;
private final String identifier;
private final String name;
public Module(String name) {
this.identifier = String.valueOf(incrementCount());
this.name = name;
MODULES.put(identifier, name);
}
private synchronized static int incrementCount() {
return ++count;
}
}