This is my code that sum variable 'res' by one 4*10^7 time using 4 threads:
class MathSin extends Thread {
public double a;
public MathSin(int degree) {
a = degree;
}
#Override
public void run() {
for (int i = 0; i < Math.pow(10., 7); i++)
MathThreads.res++;
}
}
class MathThreads {
public static double res = 0;
public static void main(String args[]) {
MathSin st = new MathSin(8);
MathSin ct = new MathSin(8);
MathSin tt = new MathSin(8);
MathSin qt = new MathSin(8);
st.start();
ct.start();
tt.start();
qt.start();
try { // wait for completion of all thread and then sum
st.join();
ct.join(); // wait for completion of MathCos object
tt.join();
qt.join();
System.out.println(res);
} catch (InterruptedException IntExp) {
}
}
}
and these are some of answers :
1.8499044E7
2.3446789E7
.
.
.
I expected get 3.0E7 but get another different answers.
how can fix this problem?
What is the problem?
You are observing race conditions while updating the static variable res.
MathThreads.res++
is equivalent to:
double tmp = MathThreads.res;
MathThreads.res = tmp + 1;
Now what happened if two threads reads at the same time a value for tmp, and both update res with tmp + 1? Well, one increment has simply been forgotten: res ends being tmp + 1 instead of being tmp + 1 + 1!
So with 4 threads updating res concurrently, you simply end up with an undefined behavior : it is impossible to predict the final value of res because of those race conditions. Two executions of the same code will give you different answers.
How to solve this issue?
To make your code thread-safe, you need to use a thread-safe structure for res: a structure that can be concurrently updated and accessed.
In your case, an AtomicLong seems the perfect choice:
public static AtomicLong res = new AtomicLong(0);
And in the run method:
for (int i = 0; i < Math.pow(10., 7); i++) {
MathThreads.res.incrementAndGet();
}
Related
I am working on Thread for the first time and I tried to code an example I saw on the internet. An ArrayList of numbers must be divided into 4 parts, and 4 separate threads need to find the odd and even numbers in those parts and add them to the "evens" or "odds" list. Although I do not have any problems with the algorithm, I have problems with Threads.
Since the codes are not very long, I am adding them completely.
My Runnable Class:
package ThreadRace;
public class OddEvenFinder implements Runnable {
private final int id;
private final int size;
public OddEvenFinder(int id, int size) {
this.id = id;
this.size = size;
}
#Override
public void run() {
int start = id * this.size;
int end = start + this.size;
while (start < end) {
if (Starter.numbers.get(start) % 2 == 0) {
Starter.evens.add(start);
}
else {
Starter.odds.add(start);
}
start++;
}
}
}
My testing class:
package ThreadRace;
import java.util.ArrayList;
import java.util.List;
public class Starter {
public static List<Integer> numbers = new ArrayList<>();
public static List<Integer> evens = new ArrayList<>();
public static List<Integer> odds = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= 10000; i++) {
numbers.add(i);
}
OddEvenFinder f1 = new OddEvenFinder(0, numbers.size() / 4);
OddEvenFinder f2 = new OddEvenFinder(1, numbers.size() / 4);
OddEvenFinder f3 = new OddEvenFinder(2, numbers.size() / 4);
OddEvenFinder f4 = new OddEvenFinder(3, numbers.size() / 4);
Thread thread1 = new Thread(f1);
Thread thread2 = new Thread(f2);
Thread thread3 = new Thread(f3);
Thread thread4 = new Thread(f4);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
System.out.println(evens.size());
System.out.println(odds.size());
}
}
When I run the application this way, the length of the evens and odds lists should be 5000-5000, but I get a result between 3000-4000.
Shouldn't the .join() function wait for threads to finish? How can there be numbers that are not included in the lists?
The interesting part is that the problem is almost resolved when I add a few words to debug.
When I edit the code like this:
#Override
public void run() {
int start = id * this.size;
int end = start + this.size;
while (start < end) {
System.out.println("Thread number " + (this.id + 1) + " is working");
if (Starter.numbers.get(start) % 2 == 0) {
System.out.println(start + " added to evens");
Starter.evens.add(start);
}
else {
System.out.println(start + " added to odds");
Starter.odds.add(start);
}
start++;
}
}
The output I get gives almost accurate results like 4999-5000. When I set the size of the numbers array to a smaller value such as 4000-5000, it gives the correct result.
I have 2 questions:
1- Why .join() is not working or what am I wrong about .join()?
2- How is it that printing a few texts makes the program run more accurately?
In the JavaDocs of ArrayList, it says in bold "Note that this implementation is not synchronised". So if several threads want to add an element at the same time, only the last call of the method will set the real value. The values of the other threads are simply overwritten. Therefore, you will get fewer numbers than expected.
In order for the list to be filled in a synchronised way, you should use the keyword "synchronized" as shown below.
synchronized (Starter.evens) {
Starter.evens.add(start);
}
and
synchronized (Starter.odds) {
Starter.odds.add(start);
}
I have two threads and they are both reading the same static variable (some big object - an array with 500_000_000 ints).
The two threads are pinned to a cpu (1 and 2) (cpu affinity) so minimize jitters.
Do you know if the two threads will slow down each other because of the static variable is read by both threads running on different cpu?
import net.openhft.affinity.AffinityLock;
public class BigObject {
public final int[] array = new int[500_000_000];
public static final BigObject bo_static = new BigObject();
public BigObject() {
for( int i = 0; i<array.length; i++){
array[i]=i;
}
}
public static void main(String[] args) {
final Boolean useStatic = true;
Integer n = 2;
for( int i = 0; i<n; i++){
final int k = i;
Runnable r = new Runnable() {
#Override
public void run() {
BigObject b;
if( useStatic){
b = BigObject.bo_static;
}
else{
b = new BigObject();
}
try (AffinityLock al = AffinityLock.acquireLock()) {
while(true){
long nt1 = System.nanoTime();
double sum = 0;
for( int i : b.array){
sum+=i;
}
long nt2 = System.nanoTime();
double dt = (nt2-nt1)*1e-6;
System.out.println(k + ": sum " + sum + " " + dt);
}
}
}
};
new Thread(r).start();
}
}
}
Thanks
In your case there won't be a slow down from doing it multi-threaded - since you're doing only reads no need to invalidate any shared state between your CPUs.
Depending on the back-ground load there could be bus limitations and stuff, but if the affinity is defined at the OS level as well - there would be more inter-CPU and inter-core communications at an easily pre-fetched manner (since you access the data sequentially) than memory-cpu communications. Back-ground load would affect the performance in single-threaded case as well - so there's no need to argue about it.
If the whole system is dedicated to your program - than you would have approximately ~20Gb/s memory bandwidth on modern CPUs which is more than enough for your data-set.
I'm currently trying to get into parallel processing, so to do this, I'm writing a program that processes an image, giving information about its color values overall- I am doing some tests on this one class with a randomly generated array of integers, and 4 threads are running to process every 4th pixel, from their respective starting places. I was just wondering if this read is thread-safe? Can multiple threads read the same data structure if that's what I want?
import java.awt.image.BufferedImage;
import java.lang.Thread;
public class ImageProcessor extends Thread {
public static void main(String[] args) {
int[] z = new int[10000000];
for (int i = 0; i < 10000000; i++) {
double a = (Math.random()*1000000);
z[i] = (int) a;
}
ImageProcessor ip = new ImageProcessor();
ip.imgRGBPercent(z);
}
public ImageProcessor() {
}
public void process(int[] x, int startPoint) {
(new Thread(new ReadThread(x, startPoint))).start();
}
public int[] imgRGBPercent(int[] x) {
ReadThread first = new ReadThread(x, 0);
ReadThread second = new ReadThread(x, 1);
ReadThread third = new ReadThread(x, 2);
ReadThread fourth = new ReadThread(x, 3);
Thread a = (new Thread(first));
Thread b = (new Thread(second));
Thread c = (new Thread(third));
Thread d = (new Thread(fourth));
long timeMetric = System.currentTimeMillis();
a.start();
b.start();
c.start();
d.start();
try {
a.join();
}
catch (Exception e) {
}
try {
b.join();
}
catch (Exception e) {
}
try {
c.join();
}
catch (Exception e) {
}
try {
d.join();
}
catch (Exception e) {
}
int redTotal, blueTotal, greenTotal;
redTotal = first.getRGBTotals()[0] + second.getRGBTotals()[0] + third.getRGBTotals()[0] + fourth.getRGBTotals()[0];
blueTotal = first.getRGBTotals()[1] + second.getRGBTotals()[1] + third.getRGBTotals()[1] + fourth.getRGBTotals()[1];
greenTotal = first.getRGBTotals()[2] + second.getRGBTotals()[2] + third.getRGBTotals()[2] + fourth.getRGBTotals()[2];
System.out.println(greenTotal);
System.out.println(System.currentTimeMillis() - timeMetric);
timeMetric = System.currentTimeMillis();
ColorValue cv1 = new ColorValue();
int sum = 0;
int sum1 = 0;
int sum2 = 0;
for (int i = 0; i < x.length; i++) {
sum += cv1.getGreen(x[i]);
sum1 += cv1.getRed(x[i]);
sum2 += cv1.getBlue(x[i]);
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - timeMetric);
int[] out = new int[3];
return out;
}
private class ReadThread implements Runnable {
private int[] colorArr;
private int startPoint, redTotal, blueTotal, greenTotal;
private ColorValue cv;
public ReadThread(int[] x, int startPoint) {
colorArr = x;
this.startPoint = startPoint;
cv = new ColorValue();
}
#Override
public void run() {
//System.out.println("hit");
for (int i = startPoint; i < colorArr.length; i+=4 ) {
redTotal += ColorValue.getRed(colorArr[i]);
blueTotal += ColorValue.getBlue(colorArr[i]);
greenTotal += ColorValue.getGreen(colorArr[i]);
}
}
public int[] getRGBTotals() {
int[] out = new int[3];
out[0] = redTotal;
out[1] = blueTotal;
out[2] = greenTotal;
return out;
}
}
}
Yes. As long as the data structure is not modified while it's being read, you're safe. Every write done before starting a thread will be visible by the started thread.
This logic would concern me a little:
for (int i = startPoint; i < colorArr.length; i+=4 ) {
redTotal += ColorValue.getRed(colorArr[i]);
blueTotal += ColorValue.getBlue(colorArr[i]);
greenTotal += ColorValue.getGreen(colorArr[i]);
}
colorArr is a reference to an array; the reference was passed to the Runnable during the constructor, but the array itself was created outside.
In the complete program you posted, I don't think it's a problem, since this array isn't modified anywhere in your program after the point where you start the threads. But in a larger, "real-world" case, you have to be aware that you're reading colorArr[i] three times and the value may not be the same each time, if there are other threads that could make changes to colorArr. That's one of the things you have to watch out for when writing concurrent code. This would be a little better:
for (int i = startPoint; i < colorArr.length; i+=4 ) {
int color = colorArr[i];
redTotal += ColorValue.getRed(color);
blueTotal += ColorValue.getBlue(color);
greenTotal += ColorValue.getGreen(color);
}
But depending on what your needs are, you may need to take extra steps to make sure no part of the program can modify colorArr at any point while the entire loop is running. Then you need to start looking into lock objects and synchronized, and you'd want to seriously consider setting up a separate class for the colorArr, with methods for modifying and reading the array that are either synchronized methods or contain logic to ensure that things are synchronized properly--by putting the array in its own class, the needed synchronization logic could be encapsulated in that class, so clients of the class wouldn't have to worry about it. That's the kind of thing you need to think about when you start using concurrency.
Yes, multiple threads can read the same objects and are fine so long as other threads aren't modifying them at the same time. Depending on what you're doing the Fork-Join framework may be useful, it manages a lot of the threading details for you, so would be worth investigating.
Are these methods getNewId() & fetchIdsInReserve() thread safe ?
public final class IdManager {
private static final int NO_OF_USERIDS_TO_KEEP_IN_RESERVE = 200;
private static final AtomicInteger regstrdUserIdsCount_Cached = new AtomicInteger(100);
private static int noOfUserIdsInReserveCurrently = 0;
public static int getNewId(){
synchronized(IdManager.class){
if (noOfUserIdsInReserveCurrently <= 20)
fetchIdsInReserve();
noOfUserIdsInReserveCurrently--;
}
return regstrdUserIdsCount_Cached.incrementAndGet();
}
private static synchronized void fetchIdsInReserve(){
int reservedInDBTill = DBCountersReader.readCounterFromDB(....); // read column from DB
if (noOfUserIdsInReserveCurrently + regstrdUserIdsCount_Cached.get() != reservedInDBTill) throw new Exception("Unreserved ids alloted by app before reserving from DB");
if (DBUpdater.incrementCounter(....)) //if write back to DB is successful
noOfUserIdsInReserveCurrently += NO_OF_USERIDS_TO_KEEP_IN_RESERVE;
}
}
No.
If 21 threads comes in here
synchronized(IdManager.class){
if (noOfUserIdsInReserveCurrently <= 20)
fetchIdsInReserve();
noOfUserIdsInReserveCurrently--;
}
and wait while another 180 threads proceed through the top and through the line below, then by the time the 21st thread reaches the line below, there will be no user ids in reserve when the 21st thread from the first group calls
return regstrdUserIdsCount_Cached.incrementAndGet();
EDIT:
Here's the initial state on class load:
regstrdUserIdsCount_Cached = 100
noOfUserIdsInReserveCurrently = 0
Let's assume that the write back to the DB is always successful. If it isn't, this code is clearly broken, because it still allocates an ID in that case.
The first thread comes through, and calls fetch because there are no ids in reserve.
regstrdUserIdsCount_Cached = 100
noOfUserIdsInReserveCurrently = 0
assuming the DB returns 100 as the initial ID, after the method completes without contention
regstrdUserIdsCount_Cached = 101
noOfUserIdsInReserveCurrently = 199
Now, let's assume 178 more threads go through without contention
regstrdUserIdsCount_Cached = 279
noOfUserIdsInReserveCurrently = 21
if that thread is preempted by another that comes through after it exits the synchronized block but before it decrements the atomic int, the preempting thread will trigger a fetch.
Since noOfUserIdsInReserveCurrently has not been decremented by the thread that was pre-empted,
(noOfUserIdsInReserveCurrently + regstrdUserIdsCount_Cached.get() != reservedInDBTill)
will be false.
Assuming that exception indicates a failure mode, we have a failure during one interleaving that is not thrown during other-interleavings. Therefore, the code is not thread-safe.
The solution is to consistently access regstrdUserIdsCount_Cached inside the critical section. In that case, it need not be an atomic int, but can simply be a non-final int.
You the field noOfUserIdsInReserveCurrently is not accessed from anywhere else, then yes - access to it is thread-safe.
P.S. if fetchIdsInReserve is called only from inside the synchronized
block in the getNewId method, then you don't have to make the method synchronized.
UPDATE: as long as the question was edited, now it is not thread-safe. You have to have the return statement in the first method INSIDE the synchronized block. And it doesn't have to be an AtomicInteger, it can be just a simple int in this case.
Here is an example test to show it is thread safe. Replace the AtomicInteger with an int and get rid of the syncs and the test should fail.
public static void main(String... arg) throws Exception {
final int loops = 1042;
for (int l = 0; l != loops; l++) {
reset(); // add this method to your class to reset the counters
final int maxThreads = 113;
final ArrayList<String> checker = new ArrayList<String>();
final CountDownLatch cl1 = new CountDownLatch(maxThreads);
final CountDownLatch cl2 = new CountDownLatch(maxThreads);
for (int x = 0; x != maxThreads; x++) {
Thread thread = new Thread(new Runnable() {
public void run() {
cl1.countDown();
try {
cl1.await(); // stack all threads here
} catch (InterruptedException e) {
e.printStackTrace();
}
int id = getNewId();
synchronized(checker) {
checker.add("" + id);
}
cl2.countDown();
}
});
thread.start();
}
cl2.await();
for (int x = 0; x != maxThreads; x++) {
String key = "" + (101 + x); // 1st ID value
if (!checker.contains(key)) {
System.out.println("Checker 1 FAIL - missing id=" + key);
} else {
checker.remove(key);
if (checker.contains(key)) {
System.out.println("Checker 2 FAIL - extra id=" + key);
}
}
}
for (int x = 0; x != checker.size(); x++) {
String key = "" + (101 + x);
System.out.println("Checker 3 FAIL - extra id=" + key);
}
}
}
I have some thread-related questions, assuming the following code. Please ignore the possible inefficiency of the code, I'm only interested in the thread part.
//code without thread use
public static int getNextPrime(int from) {
int nextPrime = from+1;
boolean superPrime = false;
while(!superPrime) {
boolean prime = true;
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
}
}
if(prime) {
superPrime = true;
} else {
nextPrime++;
}
}
return nextPrime;
}
public static void main(String[] args) {
int primeStart = 5;
ArrayList list = new ArrayList();
for(int i = 0;i < 10000;i++) {
list.add(primeStart);
primeStart = getNextPrime(primeStart);
}
}
If I'm running the code like this and it takes about 56 seconds. If, however, I have the following code (as an alternative):
public class PrimeRunnable implements Runnable {
private int from;
private int lastPrime;
public PrimeRunnable(int from) {
this.from = from;
}
public boolean isPrime(int number) {
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return false;
}
}
lastPrime = number;
return true;
}
public int getLastPrime() {
return lastPrime;
}
public void run() {
while(!isPrime(++from))
;
}
}
public static void main(String[] args) {
int primeStart = 5;
ArrayList list = new ArrayList();
for(int i = 0;i < 10000;i++) {
PrimeRunnable pr = new PrimeRunnable(primeStart);
Thread t = new Thread(pr);
t.start();
t.join();
primeStart = pr.getLastPrime();
list.add(primeStart);
}
}
The whole operation takes about 7 seconds. I am almost certain that even though I only create one thread at a time, a thread doesn't always finish when another is created. Is that right? I am also curious: why is the operation ending so fast?
When I'm joining a thread, do other threads keep running in the background, or is the joined thread the only one that's running?
By putting the join() in the loop, you're starting a thread, then waiting for that thread to stop before running the next one. I think you probably want something more like this:
public static void main(String[] args) {
int primeStart = 5;
// Make thread-safe list for adding results to
List list = Collections.synchronizedList(new ArrayList());
// Pull thread pool count out into a value so you can easily change it
int threadCount = 10000;
Thread[] threads = new Thread[threadCount];
// Start all threads
for(int i = 0;i < threadCount;i++) {
// Pass list to each Runnable here
// Also, I added +i here as I think the intention is
// to test 10000 possible numbers>5 for primeness -
// was testing 5 in all loops
PrimeRunnable pr = new PrimeRunnable(primeStart+i, list);
Thread[i] threads = new Thread(pr);
threads[i].start(); // thread is now running in parallel
}
// All threads now running in parallel
// Then wait for all threads to complete
for(int i=0; i<threadCount; i++) {
threads[i].join();
}
}
By the way pr.getLastPrime() will return 0 in the case of no prime, so you might want to filter that out before adding it to your list. The PrimeRunnable has to absorb the work of adding to the final results list. Also, I think PrimeRunnable was actually broken by still having incrementing code in it. I think this is fixed, but I'm not actually compiling this.
public class PrimeRunnable implements Runnable {
private int from;
private List results; // shared but thread-safe
public PrimeRunnable(int from, List results) {
this.from = from;
this.results = results;
}
public void isPrime(int number) {
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return;
}
}
// found prime, add to shared results
this.results.add(number);
}
public void run() {
isPrime(from); // don't increment, just check one number
}
}
Running 10000 threads in parallel is not a good idea. It's a much better idea to create a reasonably sized fixed thread pool and have them pull work from a shared queue. Basically every worker pulls tasks from the same queue, works on them and saves the results somewhere. The closest port of this with Java 5+ is to use an ExecutorService backed by a thread pool. You could also use a CompletionService which combines an ExecutorService with a result queue.
An ExecutorService version would look like:
public static void main(String[] args) {
int primeStart = 5;
// Make thread-safe list for adding results to
List list = Collections.synchronizedList(new ArrayList());
int threadCount = 16; // Experiment with this to find best on your machine
ExecutorService exec = Executors.newFixedThreadPool(threadCount);
int workCount = 10000; // See how # of work is now separate from # of threads?
for(int i = 0;i < workCount;i++) {
// submit work to the svc for execution across the thread pool
exec.execute(new PrimeRunnable(primeStart+i, list));
}
// Wait for all tasks to be done or timeout to go off
exec.awaitTermination(1, TimeUnit.DAYS);
}
Hope that gave you some ideas. And I hope the last example seemed a lot better than the first.
You can test this better by making the exact code in your first example run with threads. Sub your main method with this:
private static int currentPrime;
public static void main(String[] args) throws InterruptedException {
for (currentPrime = 0; currentPrime < 10000; currentPrime++) {
Thread t = new Thread(new Runnable() {
public void run() {
getNextPrime(currentPrime);
}});
t.run();
t.join();
}
}
This will run in the same time as the original.
To answer your "join" question: yes, other threads can be running in the background when you use "join", but in this particular case you will only have one active thread at a time, because you are blocking the creation of new threads until the last thread is done executing.
JesperE is right, but I don't believe in only giving hints (at least outside a classroom):
Note this loop in the non-threaded version:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
}
}
As opposed to this in the threaded version:
for(int i = 2;i < from;i++) {
if((number % i) == 0) {
return false;
}
}
The first loop will always run completely through, while the second will exit early if it finds a divisor.
You could make the first loop also exit early by adding a break statement like this:
for(int i = 2;i < nextPrime;i++) {
if(nextPrime % i == 0) {
prime = false;
break;
}
}
Read your code carefully. The two cases aren't doing the same thing, and it has nothing to do with threads.
When you join a thread, other threads will run in the background, yes.
Running a test, the second one doesn't seem to take 9 seconds--in fact, it takes at least as long as the first (which is to be expected, threding can't help the way it's implemented in your example.
Thread.join will only return when the thread.joined terminates, then the current thread will continue, the one you called join on will be dead.
For a quick reference--think threading when starting one iteration does not depend on the result of the previous one.