I'm new to threads. I wanted to get two threads to increment an integer to a certain value. because int type is immutable, I switched to atomic integer. I also tried to wrap an int to a class and that didn't work either. I also tried static/volatile int and that didn't work. I also tried to use fairness policy. The main issue is that "counterObj" is not incremented correctly and is still set to 0 even though it is injected to both threads.
My expected running behavior:
thread value
thread 0 0
thread 1 1
thread 0 2
...
What I wrote so far:
import java.util.concurrent.atomic.AtomicInteger;
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
System.out.println(counterObj.get());
}
}
and
import java.util.concurrent.atomic.AtomicInteger;
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public synchronized void run() {
while (counterObj.get() < bound) {
synchronized (this) {
counterObj.incrementAndGet();
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
Thread thread = new Thread(this, threadID);
thread.join();
thread.start();
}
}
Cheers!
I think your program is exiting before your threads get a chance to do anything (probably due to the ordering of your starts and joins. I would move your thread starting logic into your main(or launch) method. Something like the following.
Thread thread1 = new Thread(new MyCounterRunnable("1", counterObj, increments));
Thread thread2 = new Thread(new MyCounterRunnable("2", counterObj, increments));
Then, in your main, you need to call join after starting the threads...as follows:
thread1.start(); // starts first thread.
thread2.start(); // starts second thread.
thread1.join(); // don't let main exit until thread 1 is done.
thread2.join(); // don't let main exit until thread 2 is done.
What you really are wanting is for only one thread to increment an int at a time.
The int variable is the resource you want in the synchronized block, so the different threads can increment it one at a time.
This can be done using syncrhonize alone.
Disclaimer: I didn't run the code so it could have some typo or Exceptions to be removed from the Application class.
public class Application {
private int theVar = 0;
private int increments = 100;
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized addOne(){
this.theVar++;
}
private void launch() throws InterruptedException {
Runnable counter1 = new Counter(this, increments), counter2 = new Counter(this, increments);
Thread t1 = new Thread(counter1);
Thread t2 = new Thread(counter2);
t1.start();
t2.start();
}
}
A counter class
public class Counter implements Runnable{
private Application app;
int rounds = -1;
public Counter(Application app, rounds){
this.app = app;
this.rounds = rounds;
}
public void run(){
while(int i=0; i<rounds; i++){
this.app.addOne();
}
}
}
AtomicInteger takes care of atomicity itself, so you shouldn't need to use synchronized -- but only if you play by the rules, and do your atomic operations in one call.
You're failing to do this, because you call counterObj.get() then depending on the result counterObj.incrementAndGet(). You need to avoid this because you want the check and the update to be part of the same atomic chunk of work.
You can get close with:
while(counterObj.incrementAndGet() < bound) {} ;
But this will always increment at least once, which may be once too many.
Slightly more involved:
IntUnaryOperator incrementWithLimit = x ->
( x < bound ? x + 1 : x );
while(counterObj.updateAndGet(incrementWithLimit) < bound) {};
That is, we've created a function that increments a number only if it's lower than bound, and we tell AtomicInteger to apply that.
There are a couple of issues with your code:
Thread.join method works only if the thread has started, else it does nothing. So you must reorder your code, but if you just move the join method after start, when starting the first thread by calling CounterThread.start, the main thread will wait until the started thread has finished, blocked in the Thread.join method, and only then will continue to starting the second one. A solution is to make an additional method in the CounterThread class, that will be called after both threads have been started:
public void waitFinish() throws InterruptedException {
thread.join();
}
synchronized (this) is synchronizing on the CounterThread instance that has been created when you called new CounterThread(...), but you have two instances so each will be synchronizing on a different object. For synchronized to work, you need to use a common instance of an object, in this case you can use the shared counterObj.
Only the AtomicInteger methods are guaranteed to be thread safe, so after you check if the bound has been reached outside the synchronized block, when entering the synchronized block the value can already be changed by another thread. So you need to do a recheck inside the synchronized block OR to first synchronize on the shared lock(counterObj) before the check and increment.
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
Note that the AtomicInteger class synchronized methods aren't helping now, but because it is a mutable object, it helps to use it as a shared lock. If you used an Integer instead, being immutable, a new instance will have been created when you incremented it. So now, it's only function is a wrapper holding the integer result.
Putting it all together:
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
th1.waitFinish();
th2.waitFinish();
System.out.println(counterObj.get());
}
}
public class CounterThread implements Runnable {
private final String threadID;
private AtomicInteger counterObj;
private int bound;
private Thread thread;
public CounterThread(String threadID, AtomicInteger counter, int bound) {
this.threadID = threadID;
this.counterObj = counter;
this.bound = bound;
}
#Override
public void run() {
while (true) {
synchronized (counterObj) {
if (counterObj.get() < bound)
counterObj.incrementAndGet();
else break;
}
}
System.out.println("Thread " + threadID + " finished");
}
public void start() throws InterruptedException {
thread = new Thread(this, threadID);
thread.start();
}
public void waitFinish() throws InterruptedException {
thread.join();
}
}
I've included a double check on the AtomicInteger, this appears to be what you've been trying to accomplish.
import java.util.concurrent.atomic.AtomicInteger;
public class DualCounters{
public static void main(String[] args) throws Exception{
AtomicInteger i = new AtomicInteger(0);
int bounds = 3;
Thread a = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("a last " + last);
});
Thread b = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("b last " + last);
});
a.start();
b.start();
a.join();
b.join();
System.out.println(i.get() + " afterwards");
}
}
The double check is a broken concept in java, the AtomicInteger offers tools for accomplishing this without any synchronization.
int a;
while((a = i.getAndIncrement())<bounds){
...
}
Now a will never be greater than bounds inside of the while loop. When the loop is finished i and a could have a value greater than bounds.
If that was an issue, there is always the other method getAndUpdate
while((a = i.getAndUpdate(i->i<bounds?i+1:i)<bounds){
...
}
Related
I want to display this two threads alternatively like that :
Thread 1
Thread 0
Thread 1
Thread 0
...
That's the basic code from where I started, I tried with wait() notify() Methods but I couldn't get the result wanted.
class Task extends Thread {
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
}
}
}
public class App {
public static void main(String[] args) {
Task t1 = new Task() ;
Task t2 = new Task() ;
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
}
}
} ```
I see two solutions:
Busy Wait
Each thread wait before printing. And release when the condition is true. I used AtomicInteger for indexToPrint to make this value sync for every thread.
This solution works with n number of threads.
import java.util.concurrent.atomic.AtomicInteger;
class Task extends Thread {
final static private AtomicInteger indexToPrint = new AtomicInteger(0);
static private int threadNumber = 0;
final private int index;
/**
*
*/
public Task() {
index = threadNumber++;
}
private int nextIndex() {
return (index + 1) % threadNumber;
}
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
while (indexToPrint.get() != index) {
sleep((long) 10);
}
indexToPrint.set(nextIndex());
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {}
}
}
wait and notify
A bit more complex to understand, but no useless CPU use. Let's explain how the synchronized block synchronized (indexToPrint) {...} works.
The block is synchronized monitoring the static object indexToPrint. This object is static (common to every thread), so only one thread can simultaneously enter this block.
When one thread enter the block, if its index is different from indexToPrint then the thread is stopped with wait() making it possible for another thread to enter the block. Else, the thread name is printed, the indexToPrint is updated to next thread index and all thread are waken up with notifyAll(). Finally, it left the block.
All threads waiting are now awake, and the actual thread left the block. So one thread can try again to print.
It's important to understand that when a thread is put to wait and then notify, it runs exactly where it was stopped. Here, a thread can be stopped at two positions: before the synchronized block and at the wait call.
The while is very essential here. All thread are waking up with notifyAll(), so after waking up they should test themselves again.
You can find a good documentation here.
The code is based on the previous one. With same use of indexToPrint.
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
class Task extends Thread {
static private final AtomicInteger indexToPrint = new AtomicInteger(0);
static private int threadNumber = 0;
final private int index;
final private static ArrayList<Task> tasks = new ArrayList<>();
/**
*
*/
public Task() {
index = threadNumber++;
tasks.add(this);
}
private int nextIndex() {
return (index + 1) % threadNumber;
}
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
double dure = Math.random()*200 ;
sleep((long) dure);
synchronized (indexToPrint) {
while (indexToPrint.get() != index) {
indexToPrint.wait();
}
indexToPrint.set(nextIndex());
System.out.println(Thread.currentThread().getName());
indexToPrint.notifyAll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
The random sleep time can cause the unexpected result also within the main method making the main thread sleep between the start of Thread1 and Thread2 can help you to know who is the first thread that will start the print task , after that you should give the right sleep time inside the task to give the Threads the possibility to prints alternatively .
class Task extends Thread {
#Override
public void run() {
try {
for(int i = 0; i<10; i++){
sleep(2000);
System.out.println(Thread.currentThread().getName());
}
} catch (Exception e) {
}
}
}
public class App {
public static void main(String[] args) {
Task t1 = new Task() ;
Task t2 = new Task() ;
t1.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
}
right now i'm trying to get my head arround threads and concurrency,
so i tried to make multiple threads which counts together to 1000.
Example: Thread 1=0, Thread 2=1.Thread 3=2, and so on
As you will see in the code i implemented the Runnable interface and started the threads.
What i can see is that every thread starts the loop only for itself even if i use a synchronized method.
This is the loop "class"
private String threadname;
private int counter;
Task3(String threadname,int counter) {
this.threadname = threadname;
this.counter =counter;
}
private synchronized void compute(int i) {
try {
// "simulate" computation
System.out.println(threadname);
Thread.sleep(100);
System.out.println(" " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
for(int i=0; i <= counter;i++)
compute(i);
}
and in this class i start 4 threads with a for loop and give the method aboce the parameters which is only the thread name and how often they should count...
for(int i=0; i<=3;i++){
Runnable r =new Thread(new Task3("Thread"+i,1000));
Thread t = new Thread(r);
t.start();
}
thanks in advance
Explanation
Synchronized only means that it is ensured that a thread waits before entering the method until another thread has finished executing this method. This means that only one thread, at one time, can be inside of this synchronized method.
This can prevent strange behavior when using non-atomic operations. For example threads catching outdated values, thinking they would be up-to-date.
Solution
If you want that all threads count together you need some kind of shared resource, i.e. the counter. Currently every thread has his own counter. You need one counter in total which is shared among all threads.
A quick and dirty method would be to make the counter static. But you can probably do better with a design like this:
Class which manages the threads:
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
for (int i = 0; i < 3; i++) {
Counter counter = new Counter(demo, 1000);
counter.start();
}
}
// Provide a shared resource for all threads
private int sharedCounter = 0;
// Provide a count method for all threads
// which is synchronized to ensure that no
// strange behavior with non-atomic operations occurs
public synchronized void count() {
sharedCounter++;
}
}
And the Thread class:
public class Counter extends Thread {
private Demo mDemo;
private int mAmount;
public Counter(Demo demo, int amount) {
// Remember the shared resource
mDemo = demo;
mAmount = amount;
}
#Override
public void run() {
for (int i < 0; i < mAmount; i++) {
// Call the count method provided
// by the shared resource
mDemo.count();
// Sleep some millis
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I am trying to print numbers from 1 to 10 using three threads. thread 1 prints 1, 2 prints 2, 3 prints 3, 4 is printed by thread 1 again and so on.
I have created a shared printer resource that helps those threads to print number. But I am getting confused as how can i make the number to be visible by all threads.
The problem is eachthread is seeing their own copy of number while I need the same number to be shared by all threads.
I am trying to create this example for learning purposes. I have seen other pages on SO that had same kind of problem but I am not able to get the concept.
Any help is appreciated.
how is this example diffrent from what I am doing?
Printing Even and Odd using two Threads in Java
public class PrintAlternateNumber {
public static void main(String args[]) {
SharedPrinter printer = new SharedPrinter();
Thread t1 = new Thread(new myRunnable2(printer,10,1),"1");
Thread t2 = new Thread(new myRunnable2(printer,10,2),"2");
Thread t3 = new Thread(new myRunnable2(printer,10,3),"3");
t1.start();
t2.start();
t3.start();
}
}
class myRunnable2 implements Runnable {
int max;
SharedPrinter printer;
int threadNumber;
int number=1;
myRunnable2(SharedPrinter printer,int max,int threadNumber) {
this.max=max;
this.printer=printer;
this.threadNumber=threadNumber;
}
#Override
public void run() {
System.out.println(" The thread that just entered run "+ Thread.currentThread().getName());
for(int i =1;i<max;i++){
try {
printer.print(i,threadNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class SharedPrinter {
boolean canPrintFlag=false;
public synchronized void print(int number,int threadNumber) throws InterruptedException{
if(number%3==threadNumber) {
canPrintFlag=true;
}
while(!canPrintFlag)
{
System.out.println(Thread.currentThread().getName() + " is waiting as it cannot print " + number);
wait();
}
System.out.println(Thread.currentThread().getName()+" printed "+number);
canPrintFlag=false;
notifyAll();
}
}
//output
//The thread that just entered run 2
// The thread that just entered run 3
//The thread that just entered run 1
//3 is waiting as it cannot print 1
//1 printed 1
//1 is waiting as it cannot print 2
//3 is waiting as it cannot print 1
//2 is waiting as it cannot print 1
Technique second
it is still incomplete but I am close
output
0printed by0
2printed by2
1printed by1
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class AlternateNumber {
public static void main(String args[]) {
printerHell ph = new printerHell();
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);
for(int i=0;i<10;i++)
{
queue.add(i);
}
Thread t1 = new Thread(new myRunnableHell(queue,0,ph),"0");
Thread t2 = new Thread(new myRunnableHell(queue,1,ph),"1");
Thread t3 = new Thread(new myRunnableHell(queue,2,ph),"2");
t1.start();
t2.start();
t3.start();
}
}
class myRunnableHell implements Runnable {
BlockingQueue<Integer> queue;
int threadNumber;
printerHell ph;
myRunnableHell(BlockingQueue<Integer> queue, int threadNumber,printerHell ph) {
this.queue=queue;
this.threadNumber=threadNumber;
this.ph=ph;
};
int currentNumber;
#Override
public void run() {
for(int i=0;i<queue.size();i++)
{
currentNumber=queue.remove();
if(threadNumber%3==currentNumber)
{
ph.print(currentNumber);
}
}
}
}
class printerHell {
public synchronized void print(int Number)
{
System.out.println(Number + "printed by" + Thread.currentThread().getName());
}
}
Please see my solution here..
Using simple wait/notify
https://stackoverflow.com/a/31668619/1044396
Using cyclic barriers:
https://stackoverflow.com/a/23752952/1044396
For your query on 'How different it is from even/odd thread problem.
--> it is almost same ... instead of maintaining two states have one more state to call the third thread, so I believe,this can be extended any number of threads.
EDIT:
You may view this approach when you want to have 'n' number of threads to do the work sequentially.(Instead of having different classes t1,t2,t3 etc)
https://codereview.stackexchange.com/a/98305/78940
EDIT2:
Copying the code here again for the above solution
I tried to solve using a single class 'Thrd' which gets initialized with its starting number.
ThreadConfig class which as size of total number of threads you want to create.
State class which maintains the state of the previous thread.(to maintain ordering)
Here you go..(please review and let me know your views)
EDIT:
How it works -->
when a thread Tx gets a chance to execute.. it will set state variable's state with x. So a next thread(Tx+1) waiting , will get a chance once state gets updated. This way you can maintain the ordering of threads.
I hope i am able to explain the code. Please run it and see or let me know for any specific queries on the below code
1)
package com.kalyan.concurrency;
public class ThreadConfig {
public static final int size = 5;
}
2) package com.kalyan.concurrency;
public class State {
private volatile int state ;
public State() {
this.state =3;
}
public State(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
3) package com.kalyan.concurrency;
public class Thrd implements Runnable {
int i ;
int name;
int prevThread;
State s;
public Thrd(int i,State s) {
this.i=i;
this.name=i;
this.prevThread=i-1;
if(prevThread == 0) prevThread=ThreadConfig.size;
this.s=s;
}
#Override
public void run() {
while(i<50)
{
synchronized(s)
{
while(s.getState() != prevThread)
{
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
synchronized(s)
{
//if(s.getState() ==3)
if(s.getState()==prevThread)
System.out.println("t"+ name+ i);
s.setState(name);
i = i +ThreadConfig.size ;
s.notifyAll();
}
}
}
}
4)
package com.kalyan.concurrency;
public class T1t2t3 {
public static void main(String[] args) {
State s = new State(ThreadConfig.size);
for(int i=1;i<=ThreadConfig.size;i++)
{
Thread T = new Thread(new Thrd(i,s));
T.start();
}
}
}
OUTPUT:
t11
t22
t33
t44
t55
t16
t27
t38
t49
t510
t111
t212
t313
t414
t515
t116..............
I hope I understood you right, but there are to main "features" in java to make a variable being shared between threads:
the volatile keyword
volatile int number = 1;
AtomicInteger (a standard java class -> no library)
AtomicInteger number = new AtomicInteger(1);
These two techniques should both do what you want, however I have no experience using it, I just came upon this word, didn't know what it means and did some digging.
Some stuff to read: ;)
volatile for java explained --> http://java.dzone.com/articles/java-volatile-keyword-0
a better explanation (with IMAGES!!) but for c# (which is still the same usage) --> http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
And a link to some usages of AtomicInteger --> https://stackoverflow.com/a/4818753/4986655
I hope I could help you or at least send you in the right direction :)
- superfuzzy
I research concurrecy in java. Recently I learn wait and notify methods meaning.
Now I think that sometimes I should to solve following problem:
I have
class ThreadGroup1 extends Thread
and
class ThreadGroup2 extends Thread
I have 300 instances of every Thread and start simultaneously (for example by means of CountDownLatch )
And I have synchronized section:
synchronized(SharedObjectBetweenThreads){...}
I want to get following behaviour:
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
instance of ThreadGroup1 acquire the section
instance of ThreadGroup2 acquire the section
and so on.
I think you understand what I want.
I know that if I would use wait and notify I cannot guarantee which next thread from waiting queue will acquire section.
How can I solve described issue?
P.S.
This issue relates with question "how to notify concrete thread?"
P.S.
my current sketch
public class ConditionTest {
public static void main(String [] args){
List<Thread> threads = new ArrayList<>();
for(int i=0 ;i<10;i++) {
threads.add(new Thread1());
threads.add(new Thread2());
}
for(Thread thread : threads){
thread.start();
}
}
public static synchronized void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread{
static int index =0;
int number;
#Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
#Override
public String toString(){
return "group1-" + number;
}
Thread1(){
number= index++;
}
}
class Thread2 extends Thread{
static int index =0;
int number;
#Override
public void run(){
try {
ConditionTest.method();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
#Override
public String toString(){
return "group2-" + number;
}
Thread2(){
number= index++;
}
}
please help to correct this.
According hoaz answer I got resolving.
please review this code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionTest {
static Integer CountThreadInGroup = 10;
public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
boolean isFirstShouldExecute = true;
Condition isFirstExpected = lock.newCondition();
Condition isSecondExpected = lock.newCondition() ;
Synchronizator synchronizator = new Synchronizator(isFirstShouldExecute, lock,isFirstExpected,isSecondExpected);
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread1(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
threads.clear();
Thread.sleep(100);
for (int i = 0; i < CountThreadInGroup; i++) {
threads.add(new Thread2(synchronizator));
}
for (Thread thread : threads) {
thread.start();
}
}
public static void method() throws InterruptedException {
System.out.println(Thread.currentThread());
Thread.sleep(500);
}
}
class Thread1 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
#Override
public void run() {
synchronizator.lock.lock();
try {
while (!synchronizator.isFirstExpected) {
synchronizator.isFirstShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = false;
synchronizator.isSecondShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
#Override
public String toString() {
return "\t\t\t group1-" + number;
}
Thread1(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Thread2 extends Thread {
static int index = 0;
int number;
private final Synchronizator synchronizator;
#Override
public void run() {
synchronizator.lock.lock();
try {
while (synchronizator.isFirstExpected) {
synchronizator.isSecondShouldExecute.await();
System.out.println(Thread.currentThread() + " woke up");
}
ConditionTest.method();
synchronizator.isFirstExpected = true;
synchronizator.isFirstShouldExecute.signal();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} finally {
synchronizator.lock.unlock();
}
}
#Override
public String toString() {
return "\t\t\t\t\t\t group2-" + number;
}
Thread2(Synchronizator synchronizator) {
this.synchronizator = synchronizator;
number = index++;
}
}
class Synchronizator{
volatile boolean isFirstExpected ;
Lock lock ;
Condition isFirstShouldExecute;
Condition isSecondShouldExecute;
Synchronizator(boolean isFirstExpected, Lock lock, Condition isFirstShouldExecute, Condition isSecondShouldExecute){
this.isFirstExpected = isFirstExpected;
this.lock =lock;
this.isFirstShouldExecute = isFirstShouldExecute;
this.isSecondShouldExecute = isSecondShouldExecute;
}
}
You can find Condition and ReentrantLock classes useful in this case:
Lock lock = new ReentrantLock();
Condition threadGroup1 = lock.newCondition();
Condition threadGroup2 = lock.newCondition();
volatile boolean isFirstGroupRunning = true;
Pass all four to each thread in both groups. You can actually compose them into new class.
In first thread group use following code:
lock.lock();
try {
while (!isFirstGroupRunning) threadGroup2.await();
// do whatever you need to do in first thread
isFirstGroupRunning = false;
threadGroup1.signal();
} finally {
lock.unlock();
}
In second thread group do similar await / signal sequence:
lock.lock();
try {
while (isFirstGroupRunning) threadGroup1.await();
// do whatever you need to do in second thread
isFirstGroupRunning = true;
threadGroup2.signal();
} finally {
lock.unlock();
}
First, I suggest you not extend Thread nor call the class ThreadGroup1, etc. ThreadGroup is a core class, and there is typically no reason to extend Thread. The best way to handle the logic executed in a thread is to implement Runnable and pass instances of that class to new Thread(myRunnableInstance).
I don't think I understand what you want to really do, but it doesn't sound like threads are the way to go. Threads are meant to run multiple process at the same time, not to do them in a sequence.
It sounds like you might want a different concurrent design, maybe a 'producer consumer model' if you have two separate 'Thread groups' that are acquiring a synchronised block sequentially. In which case you could have both thread groups interacting with the same BlockingQueue. It really depends on what these threads are doing.
See
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
I am trying to write Thread Interference Example.
Below is my code:
class Counter {
private int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
Suppose Thread A invokes increment at about the same time Thread B invokes decrement.
How to implement this one.
There is not guarantee how they will run it depends on OS scheduler. There is nothing better than this
Thread a = new ThreadA();
Thread b = new ThreadB();
a.start();
b.start();
To get two threads to start executing at the same time you can use a latch. (Which is to say, two threads that become available for execution as close together as possible.) Still for a single increment/decrement each it will probably take many runs to observe an interference. For a repeatable experiment you probably want to call increment/decrement several times in parallel and observe the final value of c.
final Counter counter = new Counter()
final CountDownLatch latch = new CountDownLatch(1);
Thread thread1 = new Thread(new Runnable() {
public void run() {
latch.await();
for (int i = 0; i < 100; i++) {
counter.increment();
}
}}).start():
Thread thread2 = new Thread(new Runnable() {
public void run() {
latch.await();
for (int i = 0; i < 100; i++) {
counter.decrement();
}
}}).start():
Thread.sleep(10);//give thread 2 a timeslice to hit the await
latch.countDown();
System.out.println(counter.value()); //non-zero value indicates interference
Now in this example if you try to execute and the output false shows interference.
How it works:
Both the Runnables keep a thread local count which is incremented for each invocation of increment() and decrement(). So after execution for some amount of time if we try to validate the values
Then you can say that:
value of Counter = invocation of increment() - invocation of decrement().
But when you try to verify this at the end of execution you get false. Which shows that the actual counter value was not as expected.
public static void main(String[] args) throws InterruptedException
{
Counter c = new Counter();
IncrementingRunnable incRunnable = new IncrementingRunnable(c);
DecrementingRunnable decRunnable = new DecrementingRunnable(c);
Thread tA = new Thread(incRunnable);
Thread tB = new Thread(decRunnable);
tA.start();tB.start();
Thread.sleep(10000);
stop = true;
tA.join();
tB.join();
//verify value
int actualCount = c.c;
int expectedCount = incRunnable.count - decRunnable.count;
System.out.println(actualCount == expectedCount);
}
public static volatile boolean stop = false;
static class IncrementingRunnable implements Runnable{
volatile int count = 0;
private Counter counter;
public IncrementingRunnable(Counter c) {
this.counter = c;
}
#Override
public void run() {
while(!stop){
counter.increment();
count++;
}
}
}
static class DecrementingRunnable implements Runnable{
volatile int count = 0;
private Counter counter;
public DecrementingRunnable(Counter c) {
this.counter = c;
}
#Override
public void run() {
while(!stop){
counter.decrement();
count++;
}
}
}
Now try changing the primitive c in Counter to AtomicInteger and see the output again. You will find that now the output is true.