I'm pretty new to Concurrency but get this gist of it at the moment; I have a program that is NOT Thread Safe, so that it is possible that the invariant of the class mainly the lower bound is less than on equal to the upper bound can be broken.
I have come up with a little main method hoping it would print out false when this is true but cannot figure why it wont.
public class Conc implements Runnable {
// Invariant: lower <= upper
private final AtomicInteger lower = new AtomicInteger(0);
private final AtomicInteger upper = new AtomicInteger(0);
public void setLower(int l) {
if (l <= upper.get())
lower.set(l);
}
public void setUpper(int u) {
if (u >= lower.get())
upper.set(u);
}
public boolean isInRange(int i) {
return (i >= lower.get() && i <= upper.get());
}
public boolean invariantSatisfied() {
return (lower.get() <= upper.get());
}
public static void main(String[] args) {
Thread t1 = new Thread(new Conc());
Thread t2 = new Thread(new Conc());
Thread t3 = new Thread(new Conc());
t1.start();
t2.start();
t3.start();
}
#Override
public void run() {
for (int i = 0; i < 1000000; i++) {
setUpper(i - 10000);
setLower(i + 800000);
if (invariantSatisfied() == false) {
System.out.println("False");
}
System.out.println();
}
}
}
There are a couple of issues with this program that are causing the unexpected results.
The first as has been pointed out is that the code is actually thread safe.
This is because each Object has it's own set of fields that they are referring to and each thread has it's own object.
This can be fixed in a couple of ways
you can use the same object in each thread
Conc target = new Conc ();
Thread t1 = new Thread(target);
Thread t2 = new Thread(target);
Thread t3 = new Thread(target);
t1.start();
t2.start();
t3.start();
or you could make the fields static which would mean there is only ever one instance
private static final AtomicInteger lower = new AtomicInteger(0);
private static final AtomicInteger upper = new AtomicInteger(0);
The other issue you have is that even if this program was not thread safe the the window for the test to fail is so small that it would rarely if ever fail due to the input data.
for(int i = 0; i < 1000000; i++){
setUpper(i);
setLower(i);
if(!invariantSatisfied()){
System.out.println("False");
}
}
fixes that.
When you are creating the threads you provide to each one a new instance of Conc class. Which means that there is concurrent access to lower and upper instance variables, each thread has its own.
So you do not have a concurrency issue here, is more like a problem with your algorithm.
The code is thread-safe.
Related
There are two threads, A and B, each needing to print the numbers 1 to 100, with the constraint that thread B cannot go ahead of thread A at any point. The threads should operate independently apart from this constraint.
I tried the below approach to do so.
public class Main {
private static volatile int counter=1;
public static void main(String[] args) {
Thread t1= new Thread(()->{
for(;counter<=100;++counter)
{
System.out.println("[T1] local counter is "+counter);
}
});
Thread t2= new Thread(()->{
for(int i=1;i<=100;i++)
{
while(i>=counter)
{
System.out.println("[T2] waiting as counter value reached above A or same "+i);
}
System.out.println("[T2] local counter is "+i);
}
});
t1.start();
t2.start();
}
}
where counter is static variable.
private static volatile int counter = 1;
Is there other alternative to achieve the desired output?
I want to write a multithread app that prints characters from Strings one by one and after first "round" it would preserve order for the other rounds. It should work somehting like this:
For Strings:
private String[] strings = {"aaaa", "bb", "ccccccccccccc", "dddddd"};
It would print:
abcd abcd acd acd cd cd c c c c c c c
or maybe
dbac dbac dac dac dc dc c c c c c c c
depending on which proccess started first in the very first round
My solution so far looks like this
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class Printer {
private CyclicBarrier cyclicBarrier;
private final static String one = "aaa";
private final static String two = "bbbb";
private final static String three = "c";
private final static String four = "dddddd";
public static void main(String[] args) {
Printer printer = new Printer();
printer.runSimulation(4);
}
private void runSimulation(int numberOfStrings) {
cyclicBarrier = new CyclicBarrier(numberOfStrings, new AggregatorThread());
Thread thread = new Thread(new PrintingThread(padSpaces(one, 10)));
Thread thread1 = new Thread(new PrintingThread(padSpaces(two, 10)));
Thread thread3 = new Thread(new PrintingThread(padSpaces(three, 10)));
Thread thread4 = new Thread(new PrintingThread(padSpaces(four, 10)));
thread.start();
thread1.start();
thread3.start();
thread4.start();
}
class AggregatorThread implements Runnable{
#Override
public void run() {
System.out.print(" ");
}
}
class PrintingThread implements Runnable{
private String toPrint;
private int iterator;
public PrintingThread(String toPrint) {
this.toPrint = toPrint;
this.iterator = 0;
}
#Override
public void run() {
while(iterator < toPrint.length()) {
System.out.print(toPrint.charAt(iterator));
iterator++;
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
private String padSpaces(String inputString, int length) {
if (inputString.length() >= length) {
return inputString;
}
StringBuilder sb = new StringBuilder();
while (sb.length() < length - inputString.length()) {
sb.append(' ');
}
StringBuilder sb1 = new StringBuilder(inputString);
sb1.append(sb);
return sb1.toString();
}
}
But it doesn't preserve the order of letters written to the console and also i fill the Strings to the some hardcoded value right now, but i would want to make it work properly without equal strings.
Any suggestions on this?
Since you're asking for a solution with CyclicBarrier, here's a way you could do this with one... It definitely wouldn't be my first thought for how to solve the issue though (assuming the issue isn't 'do this with a CyclicBarrier'...).
Create a CyclicBarrier of length 4.
Assign each Thread a number (0 to 3) when it starts (using an AtomicInteger or otherwise).
Have each Thread do something like:
while (barrier.getNumberWaiting() != this.threadNumber) {
}
// Do your adding to the StringBuilder here...
barrier.await();
I.e. each Thread spins until the number of waiting parties is equal to that Thread's number.
Whichever is assigned 0 will always go through first, while all the others are stuck spinning. Once that Thread has done its StringBuilder thing, it will then await, which in turn frees the Thread assigned 1 to go through. The order will stay consistent after the number assignments.
To get the unique id per process, a simple AtomicInteger can be used.
private final AtomicInteger idCounter = new AtomicInteger();
private final CyclicBarrier barrier = new CyclicBarrier(4);
private final AtomicInteger doneCounter = new AtomicInteger();
public Runnable createRunnable() {
return () -> {
final int threadId = this.idCounter.getAndIncrement();
boolean threadDone = false;
boolean moreCharacters = true;
while (true) {
while (this.barrier.getNumberWaiting() != threadId) {
}
// Add to StringBuilder here...
// Set the 'moreCharacters' flag as false once this thread
// has handled its String.
// They will still need to spin though, to make sure the
// parties waiting keep adding up as appropriate.
if (!moreCharacters && !threadDone) {
// 'threadDone' used so that each thread only
// increments the 'doneCounter' once.
this.doneCounter.incrementAndGet();
threadDone = true;
}
barrier.await();
if (this.doneCounter.get() == 4) {
// Exit out of the loop once all Threads are done.
break;
}
}
};
}
I do not understand why each time I run this code I get different answer ?
Correct answer should be one 98098 two 98099. Anyone have any ideas why this is not working that way ? For example one time answer comes back "one 49047 two 49047" then another time it comes back "one 40072 two 40072". I am so confused at this point and lack any reasonable explanation
public class TestThreads {
public static void main(String[] args){
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 98; x++){
a.updateCounter(1000);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("one " + a.getCount());
}
}
class ThreadTwo implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 99; x++){
a.updateCounter(1);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("two " + a.getCount());
}
}
class Accum {
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
private int counter = 0;
public int getCount(){
return counter;
}
public void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
As you have two threads updating the same data without thread safety, one thread easily overwrites the value set by the other one.
Each thread works on it's own thread cached value. e.g.
Thread 1 adds 1 one hundred times. It has the value 100
Thread 2 adds 1000 one hundred times. It has the value 100000
At this point, the one value is chosen. say it's thread 1's value.
Thread 1 adds 1 one hundred times. It has the value 200
Thread 2 adds 1000 one hundred times. It has the value 100100
This time, thread 2's value is chosen.
In the end only half the updates on average are retained as the value chosen is somewhat random.
You can get to 98099 by declaring the methods in Accum as synchronized.
This will ensure that only one of the threads can access it's information at a time.
As the other answers have pointed out, you are getting unexpected results because there is nothing to stop each thread overwriting what the other had done.
Try this:
class Accum {
private static Accum a = new Accum();
public static synchronized Accum getAccum(){
return a;
}
private int counter = 0;
public synchronized int getCount(){
return counter;
}
public synchronized void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
your problem is this:
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
Since its a STATIC there is only one instance shared by all threads. so when you set it in one thread, all threads get the same new value. if you remove the static notifier and instantiate a new object of class Accum for each thread it should work.
So below is a simple Java class using multithreading, and my question is, is there a way for me to store the randomNumber from each thread (maybe in a variable called randomNumberOne or randomNumberTwo), so that I can use those to possibly get the sum of both and return it?
I know this example sounds stupid but basically with my real code I am returning a value from each of my threads and want to get the average of them. I haven't found any solution for returning values in threads in java (also I am new to multithreading completely).
public class Example {
public static void main(String[] args){
MathThread one = new MathThread();
MathThread two = new MathThread();
one.start();
two.start();
}
}
class MathThread extends Thread{
public MathThread(){
}
public void run(){
Random rand = new Random();
int randomNumber = rand.nextInt((100 - 1) + 1) + 1;
System.out.println(randomNumber);
}
Output
5
33
Add a result variable to your MathThread class and get the value after you join the thread:
class MathThread extends Thread
{
private int result;
public int getResult()
{
this.join();
return result;
}
public void run()
{
// ...
result = randomNumber;
}
}
one.start();
two.start();
double average = (one.getResult() + two.getResult()) / 2.0;
In Java 8 you can do
IntStream.of(0, 2).parallel()
.map(i -> new Random().nextInt(100)+1)
.forEach(System.out::println);
Without using the Stream API you can do
List<Future> futures = new ArrayList<>();
for (int i = 0; i < 2; i++)
futures.add(ForkJoinPool.commonPool()
.submit(new Callable<Integer>() {
public Integer call() {
return new Random().nextInt(100)+1;
}));
for(Future<Integer> future : futures)
System.out.printl(future.get());
Here is the simple snippet to customize:
// 1. Create and fill callables to execute
List<Callable<Integer>> callables = new LinkedList<>();
// callabels.addAll(makeMeCallables());
// 2. Run using Executor of your choice
ExecutorService service = Executors.newCachedThreadPool();
List<Future<Integer>> results = service.invokeAll(callables);
// 3. Get the results
if (results.get(i).isDone()) {
Future f = result.get(i);
// process f.get()
}
Is there an ExecutorService that is suitable for a huge amount of very short-lived tasks? I envision something that internally tries busy waiting before switching over to synchronized waiting. Keeping the order of the tasks is not important, but it should be possible to enforce memory consistency (all tasks happen-before the main thread regains control).
The test posted below consists of 100'000 tasks that each generate 100 doubles in a row. It accepts the size of the thread pool as command-line parameter and always tests the serial version vs. the parallel one. (If no command-line arg is given, only the serial version is tested.) The parallel version uses a thread pool of fixed size, allocation of the tasks is not even part of the time measurement. Still, the parallel version is never faster than the serial version, I've tried up to 80 threads (on a machine with 40 hyperthreaded cores). Why?
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorPerfTest {
public static final int TASKS = 100000;
public static final int SUBTASKS = 100;
static final ThreadLocal<Random> R = new ThreadLocal<Random>() {
#Override
protected synchronized Random initialValue() {
return new Random();
}
};
public class SeqTest implements Runnable {
#Override
public void run() {
Random r = R.get();
for (int i = 0; i < TASKS; i++)
for (int j = 0; j < SUBTASKS; j++)
r.nextDouble();
}
}
public class ExecutorTest implements Runnable {
private final class RandomGenerating implements Callable<Double> {
#Override
public Double call() {
double d = 0;
Random r = R.get();
for (int j = 0; j < SUBTASKS; j++)
d = r.nextDouble();
return d;
}
}
private final ExecutorService threadPool;
private ArrayList<Callable<Double>> tasks = new ArrayList<Callable<Double>>(TASKS);
public ExecutorTest(int nThreads) {
threadPool = Executors.newFixedThreadPool(nThreads);
for (int i = 0; i < TASKS; i++)
tasks.add(new RandomGenerating());
}
public void run() {
try {
threadPool.invokeAll(tasks);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
public static void main(String[] args) {
ExecutorPerfTest executorPerfTest = new ExecutorPerfTest();
if (args.length > 0)
executorPerfTest.start(new String[]{});
executorPerfTest.start(args);
}
private void start(String[] args) {
final Runnable r;
if (args.length == 0) {
r = new SeqTest();
}
else {
final int nThreads = Integer.parseInt(args[0]);
r = new ExecutorTest(nThreads);
}
System.out.printf("Starting\n");
long t = System.nanoTime();
r.run();
long dt = System.nanoTime() - t;
System.out.printf("Time: %.6fms\n", 1e-6 * dt);
}
}
The call to Executors.newFixedThreadPool(nThreads) will create a ThreadPoolExecutor that reads tasks from a LinkedBlockingQueue, ie. all threads in the executor will lock on the same queue to retrieve the next task.
Given the very small size of each task and the relatively large number of threads/cpus that you are quoting, it's most likely that your program is running slowly because of the high degree of lock contention and context switching that will be occurring.
Note that the implementation of the ReentrantLock used by LinkedBlockingQueue already spins for short periods (up to approximately 1us) while trying to acquire the lock before the thread gives up and blocks.
If your use case permits then you might want to try using the Disruptor pattern instead, see http://lmax-exchange.github.com/disruptor/