I have read through other examples, but do not understand why this code with the commented out t.join() does not always have the end value 5000 for count, but when the code is commented in, count always is 5000 at the end. But why? I thought that the static lock object can only be owned by one thread at a time and when it is owned that the other threads have to wait until it is released. So I do not understand why join() is necessary and what exactly is happening.
import java.util.ArrayList;
public class MyClass implements Runnable {
private static int count = 0;
private static Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
ArrayList<Thread> threads = new ArrayList<>();
for (int i = 1; i <= 5000; i++)
threads.add(new Thread(new MyClass()));
for (Thread t : threads)
t.start();
// for (Thread t : threads)
// t.join();
System.out.println("Total count = " + MyClass.getCount());
}
public void run() {
synchronized (lock) {
count++;
}
}
public static int getCount() {
return count;
}
}
I am kinda new to threads. How can I prove, by writing code in a separate class, that MyClass class isn't thread safe? I've been searching but I can't really find an example to aid me.
public class MyClass {
private static int value = 0;
public static void set(int setVal) {
value = setVal;
}
public static int get() {
return value;
}
public static void decrement() {
int temp = value;
value = --temp;
}
}
public static void main(String[] args) {
int nt = 10;
int c = 20000;
MyClass.set(c);
Thread[] threads = new Thread[nt];
for (int t = 0; t < nt; t++) {
Thread thread = new Thread(() -> {
for (int i = 0; i < c; i += nt) {
MyClass.decrement();
}
});
thread.start();
threads[t] = thread;
}
try {
for (Thread thread : threads) {
thread.join();
}
} catch (Throwable tr) {
tr.printStackTrace();
}
System.out.println(MyClass.get());
}
Try this. If you add synchronized to the decrement method of MyClass it will print out 0 (thread safe), but if you don't synchronize decrement than it will print out a wrong number.
This proves that MyClass (its decrement method) is not thread prove, since if it was it would print out 0.
Also, if you can't use lambdas than replace the first for loop with the following:
for (int t = 0; t < nt; t++) {
Thread thread = new Thread(() -> {
for (int i = 0; i < c; i += nt) {
MyClass.decrement();
}
});
thread.start();
threads[t] = thread;
}
Hope I could help!
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){
...
}
I have this code:
import java.util.concurrent.atomic.AtomicLong;
interface Counter {
public void increment();
public void decrement();
public int value();
}
class SynchronizedCounter implements Counter {
private int c = 0;
#Override
public synchronized void increment() {
c++;
}
#Override
public synchronized void decrement() {
c--;
}
#Override
public synchronized int value() {
return c;
}
}
class UnsynchronizedCounter implements Counter {
private int c = 0;
#Override
public void increment() {
c++;
}
#Override
public void decrement() {
c--;
}
#Override
public int value() {
return c;
}
}
public class TestProjectApp {
public static void main(String[] args) {
AtomicLong unsynchronizedErrors = new AtomicLong();
AtomicLong synchronizedErrors = new AtomicLong();
for (int i = 0; i < 1000; i++) {
Counter c = new UnsynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
unsynchronizedErrors.incrementAndGet();
}
})).start();
}
for (int i = 0; i < 1000; i++) {
Counter c = new SynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
synchronizedErrors.incrementAndGet();
}
})).start();
}
System.out.println("Unsynchronized errors: " + unsynchronizedErrors);
System.out.println("Synchronized errors: " + synchronizedErrors);
}
}
The result of execution of my program is:
Unsynchronized errors: 83
Synchronized errors: 26
I understand why there are unsynchronized errors but I don't understand why I've got synchronized errors.
My assumption is that in the second loop the thread which increment number of synchronized errors is obligated to wait until the thread which use SynchronizedCounter::increment() method. What's wrong with the way I think?
Edit:
It seems that there is no need to make those method synchronized but it's enough to use Thread::join() method in second thread. But still I don't understand why it haven't worked.
Your assumption is wrong. synchronized guarantees that the executions of your methods will not be interleaved, and that they will have an ordering. You expect the threads to run in a specific order, but you are not enforcing the order in any way.
In your second loop, you expect the threads to reach the execution of the synchronized methods in the order in which the threads are created. But what can happen in the loop body
Counter c = new SynchronizedCounter();
(new Thread(() -> {
c.increment();
})).start();
(new Thread(() -> {
if (c.value() != 1) {
synchronizedErrors.incrementAndGet();
}
})).start();
is that the Thread that you created second (the synchronizedErrors checker) runs before the first one (the one that does the incrementing). You classify this as an error, but no error has happened.
edit
The best way to fix this is to join all threads that do incrementing/decrementing before querying the state of the counter.
I am new to multi-threading and While I am reading about multi threading, thought of writing this fancy multi-threading code to do the following.
My counter class is as follows.
class Counter {
private int c = 0;
public void increment() {
System.out.println("increment value: "+c);
c++;
}
public void decrement() {
c--;
System.out.println("decrement value: "+c);
}
public int value() {
return c;
}
}
This Counter object is shared between two threads.
Once threads are started, I need to do the following.
I want Thread2 to wait until the Thread1 increments the count of the Counter object by 1.
Once this is done, Then Thread 1 informs thread2 and then Thread1 starts waiting for thread2 to decrement value by 1.
Then thread2 starts and decrements value by 1 and informs thread1 again and then thread2 start waiting for thread1. Repeat this process for few times.
How can I achieve this. Many thanks in advance.
I have done the following.
public class ConcurrencyExample {
private static Counter counter;
private static DecrementCount t1;
private static IncrementCount t2;
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(new IncrementCount(counter));
t1.start();
Thread t2 = new Thread(new DecrementCount(counter));
t2.start();
}
}
public class DecrementCount implements Runnable {
private static Counter counter;
public DecrementCount(Counter counter) {
this.counter = counter;
}
#Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.decrement();
System.out.println("decreamented");
}
}
}
public class IncrementCount implements Runnable {
private static Counter counter;
public IncrementCount(Counter counter) {
this.counter = counter;
}
#Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
System.out.println("Incremented");
}
}
}
Check out Semaphore. You'll need two, one for each thread: incSemaphore and decSemaphore. In DecrementCount do:
for (int i = 0; i < 1000; i++) {
decSemaphore.acquire();
counter.decrement();
System.out.println("decreamented");
incSemaphore.release();
}
Implement IncrementCount symmetrically. Initial value of incSemaphore should be 1 and 0 for decSemaphore.
BTW your Counter requires synchronization as well (see synchronized keyword and AtomicInteger).
Synchronizers enable threads to wait for one another. See CountDownLatch and Semaphore.
See Synchronizers section in the java.util.concurrent package
- First your increment() and decrement() must be using synchronized keyword to avoid the Race Condition See this Brian's Rule
When we write a variable which has just been read by another thread, or reading a variable which is just lately written by another thread, must be using Synchronization. And those atomic statements/Methods accessing the fields' data must be also synchronized.
- Its the JVM Thread Scheduler that has control Which thread will enter the Running State, how long its gonna stay there, and where it will go after its work has been done.
- One Cannot be sure of which thread will run first.....
- You can also use SingleThreadExecutor from java.util.concurrent, this completes one task before moving onto the second.
Use Condition with boolean flag.
final Lock lock = new ReentrantLock();
final Condition incremented= lock.newCondition();
final Condition decremented= lock.newCondition();
Change your Counter to below
Explanation :
We have used two conditions one is incremented and one is decremented. based on boolean flag we check whether we have to wait on one condition or not.
class Counter {
private int c = 0;
boolean increment = false;
final Lock lock = new ReentrantLock();
final Condition incremented = lock.newCondition();
final Condition decremented = lock.newCondition();
public void increment() throws InterruptedException {
Lock lock = this.lock;
lock.lock();
try {
while(increment)
decremented.await();
increment = true;
c++;
System.out.println("increment value: " + c);
incremented.signal();
} finally {
lock.unlock();
}
}
public void decrement() throws InterruptedException {
Lock lock = this.lock;
lock.lock();
try {
while (!increment)
incremented.await();
c--;
System.out.println("decrement value: " + c);
increment = false;
decremented.signal();
} finally {
lock.unlock();
}
}
public int value() {
Lock lock = this.lock;
lock.lock();
try {
return c;
} finally {
lock.unlock();
}
}
}