I try to learn something about multithreading and tried myself on a multithreaded counter. For my knowledge, I synchronized the counter variables but I encounter the following problems:
The threads do not take alternating turns
The counter does not count as intended (eg from 337 to 339 or from 344 to 344)
Can anyone please explain, what I did wrong?
Class RunThreads
public class RunThreads {
public static void main(String[] args) {
Thread thread1 = new Thread1();
Thread thread2 = new Thread2();
thread1.start();
thread2.start();
}
}
Class Thread1
public class Thread1 extends Thread {
public void run(){
while (ThreadCount.counter < 1000){
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try{
notifyAll();
wait();
}
catch (Exception e){}
}
}
}
class Thread2 (Yes I don't need two separate classes but it makes it easier for me to understand)
public class Thread2 extends Thread {
public void run(){
while (ThreadCount.counter < 1000){
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try{
notifyAll();
wait();
}
catch (Exception e){}
}
}
}
class ThreadCount
public class ThreadCount {
public static int counter = 0;
public static synchronized void incrementCounter(){
counter++;
}
public static void decrementCounter(){
counter--;
}
public static synchronized void printCounter(Thread t){;
Output.append(t.getName() + ":" + counter + "\n");
}
}
class Output
public class Output{
public static String value = "";
public static synchronized void append(String s) {
value+=s;
}
}
This demonstrates the pitfalls of swallowing exceptions. If you caught the exceptions in your threads and simply output them, you would observe the following:
java.lang.IllegalMonitorStateException
at java.base/java.lang.Object.notifyAll
at Thread2.run
This will happen when you call wait and notify/notifyAll on an object (the Thread objects, in this case) where you don't hold the lock by means of synchronized.
If you create a common object that both threads synchronize on, and call wait/notifyAll on, you will get what you are observing. For example:
class Thread1 extends Thread {
public void run(){
synchronized (ThreadCount.lockObj) {
while (ThreadCount.counter < 1000) {
ThreadCount.incrementCounter();
ThreadCount.printCounter(this);
try {
ThreadCount.lockObj.notifyAll();
ThreadCount.lockObj.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
The increment and the print are done in two separate operations.
So you can have (for example)
thread1: increment from 342 to 343
thread2: increment from 343 to 344
thread2: print 344
thread1: print 344
Regarding the alternating turns: both threads call wait() and notifyAll() on themselves (so, on two separate objects), and do so without holding their lock, which throws an exception. And since you ignore exceptions, you can't notice the error you made. Never ignore exceptions. Do not catch Exception.
To have alternating turns, the incrementCounter() method could look like this:
private static boolean turn;
public static synchronized void incrementCounter(){
counter++;
printCounter(Thread.currentThread());
turn = !turn;
boolean nextTurn = !turn;
ThreadCount.class.notifyAll();
while (turn != nextTurn) {
try {
ThreadCount.class.wait();
}
catch (InterruptedException e) {
return;
}
}
}
The turn boolean and the while loop might look averkill, but they're in fact necessary if you want your code to work as expected even in case of spurious wakeups.
*Thread1* ThreadCount.incrementCounter();
*Thread2* ThreadCount.incrementCounter();
*Thread1* ThreadCount.printCounter(this);
*Thread2* ThreadCount.printCounter(this);
In this action Thread 1 increment by 2 and Thread2 increment by 0.
You can use AtomicInteger etc for thread-safe operations.
You should encapsulate int. Don't leave public.
Related
I have created sample program of java Thread in which i am using stop() method to stop the thread using below program
public class App extends Thread
{
Thread th;
App(String threadName)
{
th = new Thread(threadName);
}
public synchronized void run() // Remove synchronized
{
for (int i = 0; i < 5; i++) {
System.out.println(th.getName()+" "+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
public static void main( String[] args )
{
App thread_1 = new App("Thread-1");
thread_1.start();
thread_1.setPriority(MAX_PRIORITY); //Comment this
thread_1.stop();
App thread_2 = new App("Thread-2");
thread_2.start();
}
}
The output of the above program is :
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
i.e. thread_1 is not stopped. When i am removing synchronized or priority in the code thread is stopped immediately and output will be
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
I am not able to understand why it is working like this.
Most of the public methods of the Thread class are synchronized on the Thread instance itself. http://hg.openjdk.java.net/jdk6/jdk6/jdk/file/5672a2be515a/src/share/classes/java/lang/Thread.java
Your run() method is synchronized on the Thread instance. The stop() method calls stop(Throwable), which is also synchronized on the Thread instance, its signature is:
#Deprecated
public final synchronized void stop(Throwable obj) {
The synchronization prevents the main thread from entering thread_1.stop() while the thread itself is still running in your synchronized run() method.
This is an example of why it's wise to always use private objects for synchronization. E.g., do this...
class Foobar {
private final Object lock = new Object();
public void do_something() {
synchronized(lock) {
...
}
}
}
Instead of doing this...
class Foobar {
public synchronized void do_something() {
...
}
}
The second version is more verbose (Welcome to Java!), but it prevents the user of your Foobar class from using it as a synchronization object in a way that interferes with its own use of itself as a synchronization object.
Thread.stop() is deprecated. consider using this instead:
public class App extends Thread
{
Thread th;
volatile boolean bStopThread;
App(String threadName)
{
th = new Thread(threadName);
bStopThread = false;
}
public void stopThread(){
bStopThread = true;
}
public synchronized void run() // Remove synchronized
{
for (int i = 0; i < 5; i++) {
if(bStopThread) return;
System.out.println(th.getName()+" "+i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
public static void main( String[] args ) throws InterruptedException
{
App thread_1 = new App("Thread-1");
thread_1.start();
thread_1.setPriority(MAX_PRIORITY); //Comment this
thread_1.stopThread();
App thread_2 = new App("Thread-2");
thread_2.start();
}
}
It should works as you want, although I haven't tested.
You have 3 threads in your application: main thread, running the code of the main method, thread_1 and thread_2. Your main thread starts thread_1 at some point in time X, then calls thread_1.stop() in some point in time Y, Y>X.
Now, what can happen between points X and Y, is that CPU scheduler can decide: "I will now let thread_1 run". Thread_1 will get CPU, will run and will print his text. OR, CPU scheduler can decide: "main thread is now running... let it run". And thread_1 will not get CPU until stop is called and will print nothing.
So you have uncertainty outside of your control about CPU scheduling. You can only assume that raising the priority of the thread hints scheduler to pick the first of the aforementioned choices.
But. stop is deprecated, so never use that. And don't try to guess the order of the execution of the multiple threads.
Put a try catch in your main method. Print stack trace and message of caught exception. Same in run method. Then java will tell you issue.
MHC's method is better but like I said - sometimes (rarely) when you have no control over the thread, can only call stop. But in this case you do have control over it so MHC method will work nicely.
But I do not see what is the issue with your code - it runs fine in my laptop, maybe you did not clean and re compile? Chane some message so you know latest code is running
I used :
package academic.threads;
public class StopThHighPri extends Thread {
Thread th;
volatile boolean bStopThread;
StopThHighPri(String threadName) {
th = new Thread(threadName);
bStopThread = false;
}
public void stopThread(Thread t) {
//bStopThread = true;
try {
t.stop();
} catch (Throwable e) {
System.err.println(" Stop th " + e + " " + e.getMessage());
}
}
public synchronized void run() // Remove synchronized
{
try {
for (int i = 0; i < 5; i++) {
if (bStopThread)
return;
System.out.println(th.getName() + " " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("run err " + e);
}
}
public static void main(String[] args) {
try {
System.err.println("Code version 002");
StopThHighPri thread_1 = new StopThHighPri("Thread-1");
thread_1.start();
thread_1.setPriority(MAX_PRIORITY); // Comment this
thread_1.stopThread(thread_1);
StopThHighPri thread_2 = new StopThHighPri("Thread-2");
thread_2.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("MNain err " + e);
}
}
}
Put something like System.err.println("Code version 002");
and change the 002 , 003. so you know latest code is working every time you edit the class. Again for learning this is okay but do not need to use stop here
I am trying to implement a case of shared variable like semaphores. In that I have 3 thread which should be run sequentially. below is my program. Could u tell me where I am wrong?
class Test2{
private volatile static int sharedvarNEXT = 1;
public synchronized static int getSharedvarNEXT(){
return sharedvarNEXT;
}
public synchronized static void setSharedvarNEXT(int val){
sharedvarNEXT = val;
}
public static void main(String[] s){
new classACaps().start();
new classAsmall().start();
new class1().start();
}
}
class classACaps extends Thread{
public void run(){
try{
for(char c='A';c<='Z';c++){
if(Test2.getSharedvarNEXT() == 1){
System.out.println(c);
Test2.setSharedvarNEXT(2);
notify();
} else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in A");
}
}
}
class classAsmall extends Thread{
public void run(){
try{
for(char c='a';c<='z';c++){
if(Test2.getSharedvarNEXT() == 2){
System.out.println(c);
Test2.setSharedvarNEXT(3);
notify();
} else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in a");
}
}
}
class class1 extends Thread{
public void run(){
try{
for(int c=1;c<=26;c++){
if(Test2.getSharedvarNEXT() == 3){
System.out.println(c);
Test2.setSharedvarNEXT(1);
notify();
}else {
wait();
}
}
} catch(Exception e){
System.out.println("caught in 1");
}
}
}
expected outcome is like : A, a, 1, B, b, 2......
In that I have 3 thread which should be run sequentially.
Well you're not running sequentially - you're running the three concurrently, which is the nature of what happens when you start three separate threads.
Those threads aren't synchronizing against each other at all. It doesn't really sound like you should have three threads at all, given your requirements.
Additionally:
You don't have any synchronized blocks; both wait() and notify() can only be called by a thread which owns the monitor on which they're called
Using wait() and notify() on instances of Thread is strongly discouraged, as the internals of Thread use it themselves. I suggest you create a separate object just to synchronize/wait/notify on.
Your exception handling completely ignores the exception, which has been hiding the first problem from you. Never ignore the exception - and try to avoid catching bare Exception at all, in general.
Calling notify() and wait() inside the run() method is basically calling
this.notify();
None of your Threads is synchronized on each this Thread instance.
You cannot notify() if you don't own the monitor, ie. synchronized on it. You're swallowing all the exceptions you get.
I am trying to get familiar with Java threads for the SCJP and I had a question.
In the below-written code i simply created:
two Runnables with
a common data storage (an array) and
a synchronized write() method to fill it with data successively leaving a letter as a mark for each Runnable (A and B) in sequence.
I know the code is rough and could be better written but I was seeking the moral of the threads.
So now when I run it, it never terminates and the results stop at:
Still good.
A0.
But when I change wait() to wait(100) it works just fine counting from 0 to 9 and it terminates normally. Could someone explain the reason behind that for me please?
Thank you.
public class ArrayThreads {
Object[] array = new Object[10];
boolean isA = true;
int position = 0;
int getIndex(){
return position;
}
class ThreadA implements Runnable{
synchronized void write(String value){
while(!isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("A");}
}
}
class ThreadB implements Runnable{
synchronized void write(String value){
while(isA){
try {
wait();
} catch (InterruptedException ex) {
System.out.println("An error in" + value);
ex.printStackTrace();
}
}
array[position] = value + position;
System.out.println(array[position]);
position++;
isA = !isA;
notify();
}
public void run() {
while(getIndex()<array.length){
if (getIndex()==9) return;
else
write("B");}
}
}
public static void main(String[] args){
ArrayThreads threads = new ArrayThreads();
Thread threadA = new Thread(threads.new ThreadA());
Thread threadB = new Thread(threads.new ThreadB());
System.out.println("Still good");
threadB.start();
threadA.start();
}
}
Your threads are each waiting and notifying separate objects - so they're not communicating with each other at all. If you want them to effectively release each other, they'll need a shared monitor to synchronize, wait on and notify.
It's "working" when you specify a timeout because it's effectively turning the wait call into a sleep call... still nothing is really waiting/notifying usefully, because the two threads are still dealing with separate monitors.
your objects are not working in same monitor.
you need to either move the wait() and notify() to same object like:
http://www.java-samples.com/showtutorial.php?tutorialid=306
or you can notify the target object:
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ315_016.htm
when you set wait(100). you are setting a timeout. and definitely it will wake up after 100ms.
/*
This should always produce 0 as output since all three methods increment(), decrement(), value() are thread safe(synchronized). but it is returning 1
*/
class Counter implements Runnable {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
public void run() {
try {
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
}
catch (InterruptedException e){
return;
}
}
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
new Thread(c).start();
new Thread(c).start();
System.out.println(c.value());
}
}
like everyone else said you need to make sure that the treads have finished executing, to do that you need to call join. for example
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
Thread t1 = new Thread(c).start();
Thread t2 = new Thread(c).start();
t1.join();
t2.join();
System.out.println(c.value());
}
that should run correctly
There's nothing to control when the main thread is calling value(). It will run as soon as it can acquire a lock on c, even though the other threads are still running.
If you want to wait until the threads are done, call join() on them.
You are reading the value before the threads have finished execution, so it may be well different from zero.
You're not waiting for the threads to complete running, so the result is that the value of c is printed at whatever it is at that second. I bet if you tried it 1000 times, there would be times when it wasn't 1.
IBM has a fair tutorial on the situation you're encountering:
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzahw/rzahwex3rx.htm
I'm on Java concurrency at the moment.
I don't know how to write negative scenario test.
I need a way to make deadlocks and I need a way to see that without using synchronization
I could end up with problems like inconsistency.
What is generally best way to write some stress test code
that could show me bad results if synch is omitted?
Any code example would be really appriciated.
Thank you all in advance!
The following code will almost certainly create a deadlock and demonstrates the classic deadlock scenario whereby two different threads acquire locks in an inconsistent order.
public class Main {
private final Object lockA = new Object();
private final Object lockB = new Object();
public static void main(String[] args) {
new Main();
}
public Main() {
new Thread(new Runnable() {
public void run() {
a();
sleep(3000L); // Add a delay here to increase chance of deadlock.
b();
}
}, "Thread-A").start();
new Thread(new Runnable() {
public void run() {
// Note: Second thread acquires locks in the reverse order of the first!
b();
sleep(3000L); // Add a delay here to increase chance of deadlock.
a();
}
}, "Thread-A").start();
}
private void a() {
log("Trying to acquire lock A.");
synchronized(lockA) {
log("Acquired lock A.");
}
}
private void b() {
log("Trying to acquire lock B.");
synchronized(lockB) {
log("Acquired lock B.");
}
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException ex) {
}
}
private void log(String msg) {
System.err.println(String.format("Thread: %s, Message: %s",
Thread.currentThread().getName(), msg));
}
}
The following code demonstrates a situation likely to create inconsistent results due to lack of concurrency control between two threads.
public class Main {
// Non-volatile integer "result".
private int i;
public static void main(String[] args) {
new Main();
}
public Main() {
Thread t1 = new Thread(new Runnable() {
public void run() {
countUp();
}
}, "Thread-1");
Thread t2 = new Thread(new Runnable() {
public void run() {
countDown();
}
}, "Thread-2");
t1.start();
t2.start();
// Wait for two threads to complete.
t1.join();
t2.join();
// Print out result. With correct concurrency control we expect the result to
// be 0. A non-zero result indicates incorrect use of concurrency. Also note
// that the result may vary between runs because of this.
System.err.println("i: " + i);
}
private void countUp() {
// Increment instance variable i 1000,000 times. The variable is not marked
// as volatile, nor is it accessed within a synchronized block and hence
// there is no guarantee that the value of i will be reconciled back to main
// memory following the increment.
for (int j=0; j<1000000; ++j) {
++i;
}
}
private void countDown() {
// Decrement instance variable i 1000,000 times. Same consistency problems
// as mentioned above.
for (int j=0; j<1000000; ++j) {
--i;
}
}
}
In above deadlock example. Period for deadlock is 3 second. After which lockA and lockB are released and occupied by Thread 2 and Thread 1