I have seen the example of PingPong using synchronized keyword.Basicly the actual example is this:
public class PingPong implements Runnable {
synchronized void hit(long n) throws InterruptedException {
for (int i = 1; i < 3; i++)
System.out.print(n + "-" + i + " ");
}
public static void main(String[] args) {
new Thread(new PingPong()).start();
new Thread(new PingPong()).start();
}
public void run() {
try {
Long id = Thread.currentThread().getId();
hit(id);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Normally the hit method is not synchronized because the synchronized keyword will work only if there is one object.So the result can be like 8-1 9-1 8-2 9-2 or 8-1 9-1 9-2 8-2...(It's a randomly result).But in this example it give us all time 8-1 8-2 9-1 9-2 which is a little bit strange because that mean that the hit method is synchronized!!!.
I have modified the code to check again that the hit method must be not sycnhronized so i add a Thread.sleep(1000) at the starting of the hit method it will be like
synchronized void hit(long n) throws InterruptedException {
Thread.sleep(1000);
for (int i = 1; i < 3; i++)
System.out.print(n + "-" + i + " ");
}
Now the code is giving random result each time i make an execution.
I'm really getting confusing!!
Can some one help me in understanding this issue ?
You do indeed have two separate instances of PingPong, which would mean that there would be two separate monitor objects, which should mean that the threads are not being forced to run synchronously.
I think that you are probably running into thread scheduling behavior. On a single core CPU, the code may very well execute as you describe because the thread scheduler is never given a chance to take over.
If you add a sleep to your for loop:
synchronized void hit(long n) throws InterruptedException {
for (int i = 1; i < 3; i++){
System.out.print(n + "-" + i + " ");
Thread.sleep(0);
}
}
That should release the scheduler to run other threads. Note that the JVM doesn't provide any guarantees of how the scheduler will actually behave, but in my experience the above is sufficient.
If you are on a multi-core CPU, I'd expect it to work as you expected without the sleep() call.
Not sure what is meant by synchronization. Do you want to mean that the threads are being picked up by the thread scheduler in a particular order always? If yes, that is not true. Just increase "i" from 3 to a higher value, say 10. I am seeing the following output :
12-1 11-1 12-2 11-2 12-3 11-3 12-4 11-4 12-5 11-5 12-6 11-6 12-7 11-7 12-8 12-9 11-8 11-9
Well, I have multi-core processor, hence multiple threads at the same point of time. I guess that should be the case even for you.
Related
This question already has answers here:
Why is i++ not atomic?
(10 answers)
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I wanted to test out multithreading for a project of mine, trying to also develop a solution in case something goes wrong.
So I made this small test:
main
public class main
{
static int addToCounter;
static int addToErrorCounter;
public static void main(String[] args) throws InterruptedException
{
int threads = 10;
Executor exec = new Executor();
for (int i = 0; i < threads; i++)
{
double error = Math.random();
testClass aldo = new testClass();
Thread thread = aldo.getThread(300, error);
exec.execute(thread);
}
while (threads != (addToCounter + addToErrorCounter))
{
System.out.println("Not all threads finished, number of finished threads is: " + (addToCounter + addToErrorCounter));
Thread.sleep(50);
}
System.out.println("Number of Threads that finished correctly: " + addToCounter);
}
}
testClass
import test1.main;
public class testClass
{
public Thread getThread(long time, double error)
{
Thread thread = new Thread()
{
public void run()
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (error > 0.5)
{
main.addToErrorCounter++;
throw new java.lang.Error("HELLO");
}
System.out.println("I DID THIS!");
main.addToCounter++;
}
};
return thread;
}
}
(you'll have to fix the imports, also I use a custom class Executor, although that's only a wrapper for ExecutorService)
The weird behaviour is that sometimes it works properly, and sometimes it doesn't (total terminated thread count is 9, although I can see clearly it printed "I DID THIS!" and the error exactly 10 times).
Any fix?
The Problem might be a racecondition.
the "++" operator is not atomic.
Imageine the following scenario. There are two Threads at the same time. both want to increase a number and finish.
The initial value of the number is 0.
Thread 0 reads the number, knows now it is 0.
Thread 1 reads the number, knows now it is 0.
Thread 0 (who knew it was 0) now writes 1 to the memory.
Thread 1 does not know, that the number has changed, and still believes the number is 0 so he also writes a 1 to the memory.
You need something like a synchronizing mechanisim, something like a lock, or a semaphore or something else.
have a look at this for more information: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
for your example you could use the "synchronized" example from that link.
add a method to your main class looking like this to increment the addToCounter and also to the addToErrorCounterto remove the effects from your error counter:
synchronized AddToError(int e){
addToError += e;
}
synchronized IncCounter(){
addToCounter++;
}
call those methods in your threads in the testclass instead of incrementing them unsynchronized.
My guess is that the postfix operator (main.addToCounter++) is not atomic. This line of code is probably equivalent to something like:
int temp = main.addToCounter;
main.addToCounter = temp + 1;
return temp;
With multiple threads doin this at the same time, two threads could obtain the same value for temp (because both peform the first line in the above pseudo-code before either performs the second), and hence the counter total will be too small once all threads are complete. See Why is i++ not atomic? for more information.
A quick fix in this situation is to make addToCounter an AtomicInteger, then use addToCounter.incrementAndGet() in place of addToCounter++.
everyone!
I have just created a brute force bot which uses WebDriver and multithreading to brute force a 4-digit code. 4-digit means a range of 0000 - 9999 possible String values. In my case, after clicking the "submit" button, not less than 7 seconds passes before the client gets a response from the server. So, I have decided to use Thread.sleep(7200) to let the page with a response be fully loaded. Then, I found out that I couldn't afford to wait for 9999*7,5 seconds for the task to be accomplished, so I had to use multithreading. I have a Quad-Core AMD machine with 1 virtual core per 1 hardware one, which gives me the opportunity to run 8 threads simultaneously. Ok, I have separated the whole job of 9999 combinations between 8 threads equally, each had got a scope of work of 1249 combinations + remainder thread starting at the very end. Ok, now I'm getting my job done in 1,5 hours (because the right code appears to be in the middle of the scope of work). That is much better, BUT it could be even more better! You know, the Thread.sleep(7500) is a pure waste of time. My machine could be switching to other threads which are wait() because of limited amount of hardware cores. How to do this? Any ideas?
Below are two classes to represent my architecture approach:
public class BruteforceBot extends Thread {
// All the necessary implementation, blah-blah
public void run() {
brutforce();
}
private void brutforce() {
initDriver();
int counter = start;
while (counter <= finish) {
try {
webDriver.get(gatewayURL);
webDriver.findElement(By.name("code")).sendKeys(codes.get(counter));
webDriver.findElement(By.name("code")).submit();
Thread.sleep(7200);
String textFound = "";
try {
do {
textFound = Jsoup.parse(webDriver.getPageSource()).text();
//we need to be sure that the page is fully loaded
} while (textFound.contains("XXXXXXXXXXXXX"));
} catch (org.openqa.selenium.JavascriptException je) {
System.err.println("JavascriptException: TypeError: "
+ "document.documentElement is null");
continue;
}
// Test if the page returns XXXXXXXXXXXXX below
if (textFound.contains("XXXXXXXXXXXXXXXx") && !textFound.contains("YYYYYYY")) {
System.out.println("Not " + codes.get(counter));
counter++;
// Test if the page contains "YYYYYYY" string below
} else if (textFound.contains("YYYYYYY")) {
System.out.println("Correct Code is " + codes.get(counter));
botLogger.writeTheLogToFile("We have found it: " + textFound
+ " ... at the code of " + codes.get(counter));
break;
// Test if any other case of response below
} else {
System.out.println("WTF?");
botLogger.writeTheLogToFile("Strange response for code "
+ codes.get(counter));
continue;
}
} catch (InterruptedException intrrEx) {
System.err.println("Interrupted exception: ");
intrrEx.printStackTrace();
}
}
destroyDriver();
} // end of bruteforce() method
And
public class ThreadMaster {
// All the necessary implementation, blah-blah
public ThreadMaster(int amountOfThreadsArgument,
ArrayList<String> customCodes) {
this();
this.codes = customCodes;
this.amountOfThreads = amountOfThreadsArgument;
this.lastCodeIndex = codes.size() - 1;
this.remainderThread = codes.size() % amountOfThreads;
this.scopeOfWorkForASingleThread
= codes.size()/amountOfThreads;
}
public static void runThreads() {
do {
bots = new BruteforceBot[amountOfThreads];
System.out.println("Bots array is populated");
} while (bots.length != amountOfThreads);
for (int j = 0; j <= amountOfThreads - 1;) {
int finish = start + scopeOfWorkForASingleThread;
try {
bots[j] = new BruteforceBot(start, finish, codes);
} catch (Exception e) {
System.err.println("Putting a bot into a theads array failed");
continue;
}
bots[j].start();
start = finish;
j++;
}
try {
for (int j = 0; j <= amountOfThreads - 1; j++) {
bots[j].join();
}
} catch (InterruptedException ie) {
System.err.println("InterruptedException has occured "
+ "while a Bot was joining a thread ...");
ie.printStackTrace();
}
// if there are any codes that are still remain to be tested -
// this last bot/thread will take care of them
if (remainderThread != 0) {
try {
int remainderStart = lastCodeIndex - remainderThread;
int remainderFinish = lastCodeIndex;
BruteforceBot remainderBot
= new BruteforceBot(remainderStart, remainderFinish, codes);
remainderBot.start();
remainderBot.join();
} catch (InterruptedException ie) {
System.err.println("The remainder Bot has failed to "
+ "create or start or join a thread ...");
}
}
}
I need your advise on how to improve the architecture of this app to make it successfully run with say, 20 threads instead of 8. My problem is - when I simply remove Thread.sleep(7200) and at the same time order to run 20 Thread instances instead of 8, the thread constantly fails to get a response from the server because it doesn't wait for 7 seconds for it to come. Therefore, the performance becomes not just less, it == 0; Which approach would you choose in this case?
P.S.: I order the amount of threads from the main() method:
public static void main(String[] args)
throws InterruptedException, org.openqa.selenium.SessionNotCreatedException {
System.setProperty("webdriver.gecko.driver", "lib/geckodriver.exe");
ThreadMaster tm = new ThreadMaster(8, new CodesGenerator().getListOfCodesFourDigits());
tm.runThreads();
Okay, so everyone can't wait until my question will get a response so I decided to answer it as soon as I can (now!).
If you would like to increase a performance of a Selenium WebDriver-based brute force bot like this one, you need to reject using the Selenium WebDriver. Because the WebDriver is a separate process in the OS, it does not even need a JVM to run. So, every single instance of the Bot was not only a thread managed by my JVM, but a Windows process also! This was the reason why I could hardly use my PC when this app was running with more than 8 threads (each thread was invoking a Windows process geckodriver.exe or chromedriver.exe). Okay, so what you really need to do to increase performance of such a brute force bot is to use HtmlUnit instead of Selenium! HtmlUnit is a pure Java framework, its jar could be found at Maven Central, its dependency could be added to your pom.xml. This way, brute forcing a 4-digit code takes 15 - 20 minutes, taking into account that after each attempt the website responds not faster than 7 seconds after each attempt. To compare, with Selenium WebDriver it took 90 minutes to accomplish the task.
And thanks again to #MartinJames, who has pointed that Thread.sleep() does let the hardware core to switch to other threads!
I've got a little bit of work that is easily parallelizable, and I want to use Java threads to split up the work across my four core machine. It's a genetic algorithm applied to the traveling salesman problem. It doesn't sound easily parallelizable, but the first loop is very easily so. The second part where I talk about the actual evolution may or may not be, but I want to know if I'm getting slow down because of the way I'm implementing threading, or if its the algorithm itself.
Also, if anyone has better ideas on how I should be implementing what I'm trying to do, that would be very much appreciated.
In main(), I have this:
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(numThreads*numIter);
ThreadPoolExecutor tpool = new ThreadPoolExecutor(numThreads, numThreads, 10, TimeUnit.SECONDS, queue);
barrier = new CyclicBarrier(numThreads);
k.init(tpool);
I have a loop that is done inside of init() and looks like this:
for (int i = 0; i < numCities; i++) {
x[i] = rand.nextInt(width);
y[i] = rand.nextInt(height);
}
That I changed to this:
int errorCities = 0, stepCities = 0;
stepCities = numCities/numThreads;
errorCities = numCities - stepCities*numThreads;
// Split up work, assign to threads
for (int i = 1; i <= numThreads; i++) {
int startCities = (i-1)*stepCities;
int endCities = startCities + stepCities;
// This is a bit messy...
if(i <= numThreads) endCities += errorCities;
tpool.execute(new citySetupThread(startCities, endCities));
}
And here is citySetupThread() class:
public class citySetupThread implements Runnable {
int start, end;
public citySetupThread(int s, int e) {
start = s;
end = e;
}
public void run() {
for (int j = start; j < end; j++) {
x[j] = ThreadLocalRandom.current().nextInt(0, width);
y[j] = ThreadLocalRandom.current().nextInt(0, height);
}
try {
barrier.await();
} catch (InterruptedException ie) {
return;
} catch (BrokenBarrierException bbe) {
return;
}
}
}
The above code is run once in the program, so it was sort of a test case for my threading constructs (this is my first experience with Java threads). I implemented the same sort of thing in a real critical section, specifically the evolution part of the genetic algorithm, whose class is as follows:
public class evolveThread implements Runnable {
int start, end;
public evolveThread(int s, int e) {
start = s;
end = e;
}
public void run() {
// Get midpoint
int n = population.length/2, m;
for (m = start; m > end; m--) {
int i, j;
i = ThreadLocalRandom.current().nextInt(0, n);
do {
j = ThreadLocalRandom.current().nextInt(0, n);
} while(i == j);
population[m].crossover(population[i], population[j]);
population[m].mutate(numCities);
}
try {
barrier.await();
} catch (InterruptedException ie) {
return;
} catch (BrokenBarrierException bbe) {
return;
}
}
}
Which exists in a function evolve() that is called in init() like so:
for (int p = 0; p < numIter; p++) evolve(p, tpool);
Yes I know that's not terribly good design, but for other reasons I'm stuck with it. Inside of evolve is the relevant parts, shown here:
// Threaded inner loop
int startEvolve = popSize - 1,
endEvolve = (popSize - 1) - (popSize - 1)/numThreads;
// Split up work, assign to threads
for (int i = 0; i < numThreads; i++) {
endEvolve = (popSize - 1) - (popSize - 1)*(i + 1)/numThreads + 1;
tpool.execute(new evolveThread(startEvolve, endEvolve));
startEvolve = endEvolve;
}
// Wait for our comrades
try {
barrier.await();
} catch (InterruptedException ie) {
return;
} catch (BrokenBarrierException bbe) {
return;
}
population[1].crossover(population[0], population[1]);
population[1].mutate(numCities);
population[0].mutate(numCities);
// Pick out the strongest
Arrays.sort(population, population[0]);
current = population[0];
generation++;
What I really want to know is this:
What role does the "queue" have? Am I right to create a queue for as many jobs as I think will be executed for all threads in the pool? If the size isn't sufficiently large, I get RejectedExecutionException's. I just decided to do numThreads*numIterations because that's how many jobs there would be (for the actual evolution method that I mentioned earlier). It's weird though.. I shouldn't have to do this if the barrier.await()'s were working, which leads me to...
Am I using the barrier.await() correctly? Currently I have it in two places: inside the run() method for the Runnable object, and after the for loop that executes all the jobs. I would've thought only one would be required, but I get errors if I remove one or the other.
I'm suspicious of contention for the threads, as that is the only thing I can glean from the absurd slowdown (which does scale with the input parameters). I want to know if it is anything to do with how I'm implementing the thread pool and barriers. If not, then I'll have to look inside the crossover() and mutate() methods, I suppose.
First, I think you may have a bug with how you intended to use the CyclicBarrier. Currently you are initializing it with the number of executor threads as the number of parties. You have an additional party, however; the main thread. So I think you need to do:
barrier = new CyclicBarrier(numThreads + 1);
I think this should work, but personally I find it an odd use of the barrier.
When using a worker-queue thread-pool model I find it easier to use a Semaphore or Java's Future model.
For a semaphore:
class MyRunnable implements Runnable {
private final Semaphore sem;
public MyRunnable(Semaphore sem) {
this.sem = sem;
}
public void run() {
// do work
// signal complete
sem.release()
}
}
Then in your main thread:
Semaphore sem = new Semaphore(0);
for (int i = 0; i < numJobs; ++i) {
threadPool.execute(new MyRunnable(sem));
}
sem.acquire(numJobs);
Its really doing the same thing as the barrier, but I find it easier to think about the worker tasks "signaling" that they are done instead of "sync'ing up" with the main thread again.
For example, if you look at the example code in the CyclicBarrier JavaDoc the call to barrier.await() is inside the loop inside the worker. So it is really synching up the multiple long running worker threads and the main thread is not participating in the barrier. Calling barrier.await() at the end of the worker outside the loop is more signaling completion.
As you increase the number of tasks, you increase the overhead using each task adds. This means you want to minimise the number of tasks i.e. the same as the number of cpus you have. For some tasks using double the number of cpus can be better when the work load is not even.
BTW: You don't need a barrier in each task, you can wait for the future of each task to complete by calling get() on each one.
I'm trying to understand synchronization of multiple threads in Java more fully. I understand the high level idea behind the use of the synchronized keyword, and how it provides mutual exclusion among threads.
The only thing is that most of the examples I read online and in my textbook still work correctly even if you remove the synchronized keyword which is making this topic more confusing than I think it needs to be.
Can anyone provide me with a concrete example of when not including the synchronized keyword will produce erroneous results? Any information would be much appreciated.
You can usually trigger a race condition by increasing the number of iterations. Here's a simple example that works with 100 and 1,000 iterations but fails (at least on my quad-core box) at 10,000 iterations (sometimes).
public class Race
{
static final int ITERATIONS = 10000;
static int counter;
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
Thread first = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
counter++;
}
}
});
Thread second = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
counter++;
}
}
});
first.start();
second.start();
first.join();
second.join();
System.out.println("Counter " + counter + " should be " + (2 * ITERATIONS));
}
}
>>> Counter 12325 should be 20000
This example fails because access to counter is not properly synchronized. It can fail in two ways, possibly both in the same run:
One thread fails to see that the other has incremented the counter because it doesn't see the new value.
One thread increments the counter between the other thread reading the current value and writing the new value. This is because the increment and decrement operators are not atomic.
The fix for this simple program would be to use an AtomicInteger. Using volatile isn't enough due to the problem with increment, but AtomicInteger provides atomic operations for increment, get-and-set, etc.
The thing about race conditions is that they don't necessarily happen if you don't do proper synchronization -- indeed, quite frequently it'll work just fine -- but then one year later, in the middle of the night, your code will crash with a completely unpredictable bug that you can't reproduce, because the bug only appears randomly.
Race conditions are so insidious precisely because they don't always make your program crash, and they trigger more or less randomly.
I'm writing a code that will run a multithreaded bank. I first create an array of threads with one program, then pass them into another thread that runs a loop to start them. For part of the application, I have a CPU intensive method that basically runs a series of loops within one another. Only problem is, for some reason it is not yielding the way that I think it should. Here is the code that is running the threads:
public void run(){
this.setPriority(MAX_PRIORITY);
int count = 0;
while(count<transactions.length){
int copy = count;
if(transactions[copy] instanceof Jumbler){
System.out.println(copy + " is a jumbler.");
}
else{
System.out.println(copy + " is not a jumbler");
}
transactions[copy].run();
count++;
}
}
Then here is the Jumbler run method:
public void run(){
System.out.println("running jumbler");
Thread.yield();
Thread.currentThread().yield();
try{
Thread.currentThread().sleep(5000);
}catch(InterruptedException e){}
//this.setPriority(MIN_PRIORITY);
System.out.println("still running.");
Thread.yield();
nums = new int[1000];
int i = 0;
do{
Thread.yield();
for(int x=0;x<1000;x++){
Thread.yield();
//System.out.println("in the loop");
nums[x]=(int)(Math.random()*10000)+1;
for(int y = 0;y<1000;y++){
Thread.yield();
//System.out.println("in the the loop");
for(int z = 0;z<100;z++){
Thread.yield();
}
}
}
Thread.yield();
i++;
System.out.println(whichJumble + ": " + i);
}while(i<1000);
}
So, the problem is that I want it to yield, allowing the main method to continue running more threads, but it blocks and waits for the Jumbler to complete (which takes a long time). Any idea why that would happen or how to fix it?
I suppose the issue comes with transactions[copy].run(); in your main loop. This one calls the run method directly but not in another system thread. Instead start the thread with transactions[copy].start();.
It seems that you're spawning the thread correctly (in fact, you're not spawning them at all)
If you want a Thread to start running (concurrently to the current thread) you need to call the start() method of that Thread object, which you don't.
If I understand your code correctly, you want the first snippet to spawn the other threads. Therefore you should change transactions[copy].run() to transactions[copy].start().
(This an educated guess. It would be nice if you showed the definition of the transaction array.)
Here's the typical scheme of launching several Threads:
class MyThread extends Thread {
public void run() {
// Do something here ...
}
}
// Prepare the array
MyThread[] arr = new MyThread[10];
for(int i = 0; i < arr.length; ++i)
arr[i] = new MyThread();
...
// Launch the threads
for(int i = 0; i < arr.length; ++i)
arr[i].start();
Once the thread is running, i don't think you can be guaranteed that priority changes when you call setPriority.
these two statements do the same thing:
Thread.yield();
Thread.currentThread().yield();
but you probably shouldn't be calling yield, let the os do that.