This question already has answers here:
Thread safety in java multithreading
(3 answers)
Difference between volatile and synchronized in Java
(4 answers)
Closed 1 year ago.
My problem is that the code should increment a 1000 times and then output it. But sometimes a isn't 1000 at the end.
public class Counter extends Thread {
private static Integer a = 0;
public void run() {
for (int i = 0; i < 100; i++) {
a++;
}
}
public static void main(String[] args) {
Counter[] ca = new Counter[10];
for (int i = 0; i < 10; i++) {
ca[i] = new Counter();
ca[i].start();
}
for (Counter c : ca) {
try {
c.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(a);
}
This code is the original code that is obviously not going to work because I have multiple Threads accessing the variable a. I've tried putting a synchronized(this) around a++; and marking a as volatile but I still sometimes get a false Result. The only way I've found to make it work reliably it to put join() into the for loop, but that kind of defeats the point of using Threads in the first place.
Any help is appreciated.
There are several problems in the code you posted, and all them a reported in the comments to your qestion.
I try to show the major ones:
Variable a is Integer which is immutable, this means that a++ really means create a new Ineger instance containing the old value plus 1.
the variable a is updated by multiple threads concurrenlty without synchonizazion, this means that the operation a=a+1 canbe split in read a, increment a; if two or more thread read a at the same time the the increment by one the same value
Here is a modified version that uses a Lock to synchronize access to the resource. The main scope of this code is to show that the access to a must be synchronixed between thread; in order to get a "clean design" you must refactor/change a lot of other things.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SyncProblem {
private static int a=0;
private static class IncThread extends Thread {
private Lock lock;
public IncThread(Lock lock) {
this.lock=lock;
}
public void run() {
lock.lock();
try {
for (int i = 0; i < 100; i++) {
a++;
}
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
Lock lock= new ReentrantLock();
IncThread[] ca = new IncThread[10];
for (int i = 0; i < 10; i++) {
ca[i] = new IncThread(lock);
ca[i].start();
}
for (IncThread c : ca) {
try {
c.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(a);
}
}
Related
This question already has answers here:
Incrementing AtomicInteger in Java in 1000 threads does not generate value 1000 [duplicate]
(2 answers)
Closed 5 years ago.
My expectation was that the program would return the output "1000".
However, every time the program performs a different output occurs.
The increment() method of the Counter class has been synchronized. Would only this be necessary to avoid competing readings?
What would be the correct way to make it count the 1000 increments?
package app;
public class Counter {
private Integer value;
public Counter(int initialValue) {
value = initialValue;
}
public synchronized void increment() {
value = value + 1;
}
public int getValue() {
return value;
}
}
package app;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
System.out.println(contador.getValue());
}
}
Your logic is fine.
The problem is that you print the value of the counter before the threads finished incrementing it.
Change your code to this:
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown(); //Shut down the executor
//Wait until the threads have stopped. A maximum of 1 minute is more than enough
executor.awaitTermination(1, TimeUnit.MINUTES);
System.out.println(contador.getValue()); //prints 1000
The answer to your question is that you're not waiting for all your Runnables to finish before printing the value of contador.
So sometimes only 20 calls to increment have been done called and sometimes 50 have been done, etc
Edit:
Looking closer, I think you have a potential issue with your thread safety. You've synchronized the increment value. Should the getValue method match?
For example, if Thread A is in the process of incrementing, what should Thread B see when it calls getValue? Should it see the old value, or should it wait until Thread A is done so it gets the latest value?
This is how your main method should look:
public static void main(String[] args) {
Counter contador = new Counter(0);
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executor.submit(() -> {
contador.increment();
});
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
}
System.out.println(contador.getValue());
}
This question already has answers here:
Synchronization on immutable objects (in java)
(4 answers)
Closed 6 years ago.
I'm new to java and was trying out synchronization with a sample program to add numbers upto 100 using multiThreading. And following is code i was able to come up with. When i test the code it sometimes gives the correct value of 4590 but sometimes doesnt give the correct value. Can anyone point out what i'm doing wrong
class Counter{
Integer counter = 0;
public void increment(int i){
synchronized (counter){
counter += i;
}
}
}
class ObjectTest implements Runnable{
int i;
Counter blah;
public ObjectTest(Counter counter,int i){
blah =counter;
this.i = i;
}
#Override
public void run() {
blah.increment(i);
}
}
public class SyncTest {
public static void main(String args[]) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(4,10,60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
Counter counter = new Counter();
for (int index = 0; index < 100; index++) {
ObjectTest objectTest = new ObjectTest(counter,index);
executor.execute(objectTest);
}
executor.shutdown();
while (!executor.isTerminated()){
Thread.sleep(1000L);
}
System.out.println(counter.counter);
}
}
You can't synchronize on counter because it's an Integer, which is immutable. Therefore counter += i creates a new Integer object, which is not the same that was synchronized on.
You can make it int counter and have a separate Object lock = new Object();, synchronizing on lock.
Class C:
class C extends Thread
{
public static int cr;
C(int n)
{
cr = n;
}
public void run()
{
go();
}
synchronized void go()
{
for (int i = 0; i < 10000; i++)
{
cr++;
}
}
}
Class Launch
class Launch
{
public static void main(String args[]) throws InterruptedException
{
C[] c = new C[10];
for (int i = 0; i < 10; i++)
{
c[i] = new C(0);
}
for (int i = 0; i < 10; i++)
{
c[i].start();
}
System.out.println(C.spaces);
}
}
It doesn't give me 100,000, but rather numbers below 100k. Why? I made method go() synchronized, so it should be used by only one thread at a time..? What am I missing?
synchronized void go(){...} means that it is synchronized on current instance (on this). Since this method belongs to your custom Thread class and you are crating 10 threads there exist 10 different this references.
That is one of the reasons it is preferred to not extend Thread class, but to implement Runnable interface and pass instance of this interface to as many threads as you want.
Another problem is that you are printing edited value without waiting for threads to finish.
What you need is creating one instance which will hold value you want to change and invoke synchronized method from only one instance, because as mentioned by default synchronized void method is synchronized on this (current object on which this method is invoked).
class MyTask implements Runnable {
public volatile int counter;
MyTask(int n) {
counter = n;
}
public void run() {
System.out.println(Thread.currentThread().getName()+" entered run");
go();
System.out.println(Thread.currentThread().getName()+" finished run");
}
synchronized void go() {
System.out.println(Thread.currentThread().getName()+" entered go");
for (int i = 0; i < 10000; i++) {
counter++;
}
System.out.println(Thread.currentThread().getName()+" left from go");
}
}
class Luncher {
public static void main(String args[]) throws InterruptedException {
//lets create task we want to execute in parallel
MyTask task = new MyTask(0);
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++)//create thread instances
threads[i] = new Thread(task);
for (int i = 0; i < 10; i++)//start threads
threads[i].start();
for (int i = 0; i < 10; i++)
threads[i].join();//hold main thread to wait till all threads will finish
System.out.println(task.counter);
}
}
with
c[i] = new C(0);
you are creating new instance of c every time
with
synchronized void go()
{
for (int i = 0; i < 10000; i++)
{
cr++;
}
}
you will always get the number less than 10000 i dont know why you are expecting 100,000
Is it a typo mistake i < 10000 where you should have u used 100,000 ?
To answer your last question
I made method go() synchronized, so it should be used by only one thread at a time..?
if only one thread at a time, you don't need synchronized(multithreading concept).
It doesn't give me 100,000, but rather numbers below 100k. Why?
Every thing is working fine but main thread is not waiting for other threads to complete the calculation hence output is random in main thread.
Use Thread#join() so that main thread waits for all the other threads to die before executing the last line of the main thread.
for (int i = 0; i < 10; i++) {
c[i].start();
c[i].join(); // Waits for this thread to die
}
System.out.println(C.cr); // output 100000
It's worth reading How do I pause main() until all other threads have died?
Hi for my java revision I'm going through past paper questions and I'm stuck. I'm given this code:
class FriendFinderThread extends Thread {
// number of FriendBook friends
int numFriends = 0;
public void run() {
// join, then leave FriendBook
FriendBook.join(this);
try { Thread.sleep(10000); }
catch (InterruptedException(ie) {}
FriendBook.leave(this);
}
}
class FriendBook {
// list of FriendBook members
static Vector<FriendFinderThread> members =
new Vector<FriendFinderThread>();
static void join(FriendFinderThread f) {
// add a new friend to all existing members
int size = members.size();
for (int i = 0; i < size; i++) {
members.elementAt(i).numFriends++;
}
f.numFriends = size; // new member’s friends
members.add(f); // add to list of members
}
static void leave(FriendFinderThread f) {
members.remove(f); // remove from list
int size = members.size();
for (int i = 0; i < size; i++) {
members.elementAt(i).numFriends--;
}
}
public static void main() {
for (int n = 0; n < 100; n++) {
new FriendFinderThread().start();
}
}
}
I'm having real trouble understanding what is going on, could someone please explain what is happening in the code and how the code could have problems with interference.
Thank you
At some point one thread will call join. This uses members.size() and accesses each element in members. While doing so another member will leave (the later threads will be slower as they loop over more elements, so at some point there will be more leaving than joining). This means that members.elementAt(members.size()-1) will throw an error.
A simple multithreading test with synchronization. I thought if it was "synchronized," other threads would wait. What am I missing?
public class MultithreadingCounter implements Runnable {
static int count = 0;
public static void main(String[] args) {
int numThreads = 4;
Thread[] threads = new Thread[numThreads];
for (int i = 0; i < numThreads; i++)
threads[i] = new Thread(new MultithreadingCounter(), i + "");
for (int i = 0; i < numThreads; i++)
threads[i].start();
for (int i = 0; i < numThreads; i++)
try {
threads[i].join();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
increment();
}
public synchronized void increment(){
System.out.print(Thread.currentThread().getName() + ": " + count + "\t");
count++; // if I put this first or increment it directly in the print line, it works fine.
}
}
I thought this would display something like:
0: 1 2: 0 1: 2 3: 3
But its actual output:
0: 0 2: 0 1: 0 3: 3
and other variations like this. It should display each increment (i.e. 0,1,2,3) not in order...
Your synchronized keyword is on an instance method. No two threads can execute this method of one of your thread objects at the same time. But, that is not what your code does. Each thread executes the method on its own instance. The synchronization does not do what you seem to intend. If it were a static method, it would.
Your increment method should be static:
public static synchronized void increment() {
Right now, each object is synchronized on that individual instance, but since count is a static variable, you should be synchronizing on the Class object itself.
when synchronized keyword is used before a method, it ensures that that method can be executed by only one thread at a time with respect to that object only. It does not ensure thread safety from other objects.