why this synchronized method is not working as expected? - java

Could someone explain two me why these to codes dont output the same results (the only difference between two codes is in the run() method) ?
NB: the first code seems not doing any lock!
First Code:
class LetterThread extends Thread
{
private StringBuffer letter;
public static void main(String[] args) {
StringBuffer sbltr = new StringBuffer("A");
LetterThread one = new LetterThread(sbltr);
LetterThread two = new LetterThread(sbltr);
LetterThread three = new LetterThread(sbltr);
one.setName("Thread ONE");
two.setName("Thread TWO");
three.setName("Thread THREE");
one.start();
two.start();
three.start();
}
LetterThread(StringBuffer letter) {
this.letter = letter;
}
public synchronized void run() {
{
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + " (" + x
+ ") = " + letter);
}
letter.setCharAt(0, (char) (letter.charAt(0) + 1));
}
}
}
Second Code: this code is working exactely as expecting to
class LetterThread extends Thread
{
private StringBuffer letter;
public static void main(String[] args) {
StringBuffer sbltr = new StringBuffer("A");
LetterThread one = new LetterThread(sbltr);
LetterThread two = new LetterThread(sbltr);
LetterThread three = new LetterThread(sbltr);
one.setName("Thread ONE");
two.setName("Thread TWO");
three.setName("Thread THREE");
one.start();
two.start();
three.start();
}
LetterThread(StringBuffer letter) {
this.letter = letter;
}
public void run() {
synchronized (letter) {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + " (" + x
+ ") = " + letter);
}
letter.setCharAt(0, (char) (letter.charAt(0) + 1));
}
}

First Code
The thing is that you have 3 instances of a thread and each threads runs it's own synchronized instance of the method run(). But there is always only one thread that is wating to be synchronized to it's own run() method, so it will run whenever the threads wants it to run. This results in no synchronization at all.
Second Code
You have also 3 instances of a thread, but they share a reference to the letter object. Therefore if you lock this reference, the threads will exclude each other and the code runs as expected.
Additional Information
This post explains pretty good why the first solution doesn't work: Should you synchronize the run method? Why or why not?

When you want to synchronize two threads you must lock on a shared resource by all threads. Synchronizing in the run method(or any instance method in thread class) each thread locks it's own method resulting no synchronization at all.

Related

Why non-blocking algorithm does not work correctly

I am writing a thread safe counter. When I test and the threads go first one, then the second everything works correctly. But when threads enter the increment () method at the same time, the counter does not work properly. The reason is not clear, I am using atomic integer.
public class CASCount {
private final AtomicReference<Integer> count = new AtomicReference<>(0);
private AtomicInteger oldValue = new AtomicInteger(0);
private AtomicInteger newValue = new AtomicInteger(0);
public void increment() {
do {
oldValue.set(count.get());
System.out.println(oldValue + " old");
if (oldValue.get() == -1) {
throw new UnsupportedOperationException("Count is not impl.");
}
newValue.incrementAndGet();
System.out.println(newValue + " new");
} while (!count.compareAndSet(oldValue.get(), newValue.get()));
}
public int get() {
int result = -1;
result = count.get();
if (result == -1) {
throw new UnsupportedOperationException("Count is not impl.");
}
return result;
}
}
#Test
public void whenUseCASCount() throws InterruptedException {
CASCount count = new CASCount();
Thread one = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("one");
count.increment();
}
});
Thread two = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("two");
count.increment();
}
});
one.start();
two.start();
one.join();
two.join();
assertThat(count.get(), is(10));
}
its my decision
private final AtomicReference<Integer> count = new AtomicReference<>(0);
public void increment() {
int current, next;
do {
current = count.get();
next = current + 1;
} while (!count.compareAndSet(current, next));
}
public int get() {
return count.get();
}
TL;DR - Make your increment method synchronized.
Details - Even though you have atomic variables that you use, that does not mean that your class is thread safe. It's not safe because there can be (and are) race conditions between the checks and increments for your variables.
do {
oldValue.set(count.get());
System.out.println(oldValue + " old");
if (oldValue.get() == -1) {
throw new UnsupportedOperationException("Count is not impl.");
}
newValue.incrementAndGet(); <--- between here
System.out.println(newValue + " new");
} while (!count.compareAndSet(oldValue.get(), newValue.get())); <--- and here
A typical case of check-then-act race condition.
This happens because your atomic variables can be accessed by multiple threads and their shared state can mutate from one thread and not be seen in another.
To preserve state consistency, update related state variables in a single
atomic operation.
- Java Concurrency in Practice
Hence, we use intrinsic locks (built-in synchronized) to make the method safe when multiple threads access it. What happens is that the state of the atomic variables would not change because each thread will access the increment method one at a time.

Java program freezes when using wait and notifyAll

I'm trying to get into the nitty gritty of understanding how wait and notifyAll work and have hit a roadblock.
This program downloads a long text document, starts multiple threads to count characters and then outputs the count totals.
I'm using wait and notifyAll to control the thread execution so that they are completed in alphabetical order. Here's the code. I'll follow with an explanation of the problem.
public class Test {
public static void main(String[] args) {
//code that reads in the data
LongTask a = new LongTask(buffer, 'a', "Thread_a", 0);
a.start();
LongTask b = new LongTask(buffer, 'b', "Thread_b", 1);
b.start();
//Repeat code for all other characters
a.join();
System.out.println("Alphabet count is: " + SharedResults.getResults());
LongTask class contains constructor and run()
public class LongTask extends Thread {
//Instance variables created here
//LongTask constructor
public LongTask (StringBuffer buffer, char target, String name, int turn)
{
super(name);
this.sharedData = sharedData;
inputData = buffer;
this.target = target;
this.turn = turn;
}
//Run method iterates through input data and counts matching characters,
//then calls addToResults
public synchronized void run()
{
//Thread t = Thread.currentThread();
String name = this.getName();
int runTurn = this.turn;
System.out.println(name + " running - Turn " + runTurn);
Integer count = 0;
for (int i = 0; i < inputData.length(); i++) {
if (inputData.charAt(i) == target) {
count ++;
}
}
ResultsEntry newResult = new ResultsEntry(count, target);
SharedResults.addToResults(newResult, turn);
}
}
SharedResults class adds results to Array. addToResults method performs this action and controls the synchronization.
public class SharedResults extends Thread{
//Code that creates array
//Code for SharedResults constructor
public synchronized static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread t = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
while (turn != results.size()){
try {
System.out.println("Wait printout");
t.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(t.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
t.notifyAll();
}
Here's what I'm seeing when I watch this step through in Debug.
-Input executes and all LongTask threads start
(Thread_a should be the first thread to execute addToResults)
-Some threads (not Thread_a) hit the while evaluation of addToResults and do not proceed
-Thread_a hits the while evaluation and fully executes. (Now it should be Thread_b's turn)
-Thread_e executes the "Wait printout" (just a debugging feature that tells me when a thread is waiting) and then the program hangs.
It looks to me like I haven't set up wait correctly. The program actually worked (or appeared to be) correctly until I added in the sysout. Any ideas what's going on here?
To answer my own question,
This was covered in this thread.
The problem is that notifyAll() notify all of that object's threads that are waiting. Because I was calling wait() on each thread, the notifyAll() from another thread wasn't notifying any of the other threads.
As suggested by the linked post, I created a static synchronized object and called the wait and notify methods on that object. The resulting code looked like this:
private static final Object LOCK = new Object();
public static void addToResults(ResultsEntry newResult, int turn)
{
Integer resultsCount = newResult.getCount();
char resultsTarget = newResult.getTarget();
Thread thread = Thread.currentThread();
/*
* Turn number is compared to the size of the results array to control the
* order of execution.
*/
synchronized (LOCK){
while (turn != results.size()){
try {
System.out.println(thread.getName() + " is waiting");
LOCK.wait();
} catch (InterruptedException e) {}
}
System.out.println(thread.getName() + " is adding " + newResult);
SharedResults input = new SharedResults(resultsCount, resultsTarget);
System.out.println("Cumulative Results are " + results);
LOCK.notifyAll();
}
}
Thanks to all who commented!

start multiple threads at the same time

For our assignment for class, we have to count the amount of words in a txt file by splitting it into n segments, which we are supposed to be able to set before launching the programm. Each segment should then get its own thread, which counts the words and then stops. At the end, the main thread should collect all the individual word counts and add them together.
This is (part of) what I wrote so far
for (int i = 0; i < segments; i++){
Thread thread = new Thread();
thread.start();
int words = counting(stringarray[i]);
totalwords += words;
long nanos = ManagementFactory.getThreadMXBean().getThreadCpuTime(Thread.currentThread().getId());
System.out.println("This Thread read " + words + " words. The total word count now is " + totalwords +
". The time it took to finish for this thread is " + nanos +".");
System.out.println("Number of active threads from the given thread: " + Thread.activeCount());
}
Now, while this gets the primary job done (counting the words in different threads and adding them to the total), I dont know how to just "leave the thread be" and then add the individual wordcounts together after every thread has done its job.
Additionally, while this is definitely starting multiple threads, it only ever prints out that I have 2, or maybe 3 threads running at a time, even if I split the txt into 100 segments. Is there a way to have them all run at the same time?
The wording of the question suggest that each thread has its own counter, so I would declare a thread class:
public class WordCounter extends Thread {
private String text;
private int count;
public WordCounter(String text) {
this.text = text;
}
public int getCount() {
return count;
}
#Override
public void run() {
count = counting(text);
}
}
and use it as follows:
WordCounter[] threads = new WordCounter[segments];
for (int i = 0; i < segments; ++i) {
threads[i] = new WordCounter(stringarray[i]);
threads[i].start();
}
int total = 0;
for (int i = 0; i < segments; ++i) {
threads[i].join();
total += threads[i].getCount();
}
You may use next code snippet as a basis.
Note, that in case you increment common variable in different threads, this operation has to be thread-safe. That's why AtomicInteger variable is used as a counter
final List<String> segments = new ArrayList<>();
//TODO:Fill segments ... this is up to you
//In case threads will increment same variable it has to be thread-safe
final AtomicInteger worldCount = new AtomicInteger();
//Create Thread for each segment (this is definitely not optimal)
List<Thread> workers = new ArrayList<>(segments.size());
for (int i = 0; i < segments.size(); i++) {
final String segment = segments.get(i);
Thread worker = new Thread(new Runnable() {
#Override
public void run() {
//increment worldCount
worldCount.addAndGet(counting(segment));
}
});
workers.add(worker);
worker.start();
}
//Wait until all Threads are finished
for (Thread worker : workers) {
worker.join();
}
int result = worldCount.get();
Same solutions, but with Executors:
final List<String> segments = new ArrayList<>();
segments.add("seg1");
segments.add("seg2");
segments.add("seg 3");
final AtomicInteger worldCount = new AtomicInteger();
List<Future> workers = new ArrayList<>(segments.size());
ExecutorService executor = Executors.newFixedThreadPool(segments.size());
for (String segment : segments) {
Future<Integer> worker = executor.submit(() -> worldCount.addAndGet(counting(segment)));
workers.add(worker);
}
executor.shutdown();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.out.println("Still waiting...");
System.exit(0);
}
int result = worldCount.get();
System.out.println("result = " + result);

multi-threading in Java working even without dekker/pterson's algorithm?

Yes, this is a homework assignment, but I have tried everything possible and can't come up with a possible. The point of this assignment is to illustrate that, before implementing the dekker's algorithm / peterson's algorithm, it is very likely that two processes will not go one after another.
import java.util.*;
public class myProcess
{
private static final Random R = new Random();
private int id;
public myProcess(int i){
id = i;
}
private static void delay(int value){
try{
java.lang.Thread.sleep(R.nextInt(value));
}
catch(InterruptedException e){
}
}
public void run(){
System.out.println("");
delay(20);
System.out.println(this.id + " is starting");
delay(20);
System.out.println("LINE ONE");
delay(20);
System.out.println("LINE TWO");
delay(20);
System.out.println("LINE THREE");
delay(20);
System.out.println(this.id+ " is ending ");
delay(20);
}
public static void main(String [] args){
final int N = 2;
myProcess[] t = new myProcess[N];
for(int i = 0; i < N; i++){
t[i] = new myProcess(i);
t[i].run();
}
}
Right now the output is
0 is starting
LINE ONE
LINE TWO
LINE THREE
0 is ending
1 is starting
LINE ONE
LINE TWO
LINE THREE
1 is ending
but it should be all mixed up to illustrate that processes don't necessarily wait for another one to finish.
I tried other methods of defining run() such as
String[] statements = new String[5];
statements[0] = "Thread " + this.id + " is starting iteration ";
statements[1] = "We hold these truths to be self-evident, that all men are created equal,";
statements[2] = "that they are endowed by their Creator with certain unalienable Rights,";
statements[3] = "that among these are Life, Liberty and the pursuit of Happiness.";
statements[4] = "Thread " + this.id+ " is done with iteration ";
for(int i = 0; i< 5; i++){
System.out.println(statements[i]);
delay(20);
}
but it still does not return to me any "wrong outputs"
What am I doing so wrong that's making the output so right?
You should call start() function on your thread, not run().
Edit: Also your class should implement Runnable interface or extend Thread class.
You are not creating new Threads in your code and everything is running in one thread.
public class myProcess extends Thread
...
for(int i = 0; i < N; i++){
t[i] = new myProcess(i);
t[i].start();
}
I would guess that your delays are too short to see any significant mixing. You pass in 20, as if it's 20 seconds, but it's only 20 milliseconds of sleep. Pass in 20,000 and see if you get the behavior you expect.
Change your delay method to look like the following. According to this post (https://stackoverflow.com/a/1600603/1265692), the Java sleep method is not guaranteed to relinquish control over the cpu. By adding the yield call, you remind Java to let other Threads run.
private static void delay(int value){
try{
java.lang.Thread.sleep(R.nextInt(value));
java.lang.Thread.yield();
}
catch(InterruptedException e){
}
}

How to remove manually created pauses in Main-thread?

Problem description:
We have a given matrix randomly filled with digits and have to create separate threads for each row of the matrix that count how many times the digits encounter in that row.
Without these sleeps in the main thread, it's not working correctly..
Here's my solution.
Also it's following here:
public class TestingMatrixThreads {
public static void main(String[] arr) throws InterruptedException {
int[][] a = new int[67][6];
// class.Count works with class.Matrix, that's why I've made it this way
Matrix m = new Matrix(a);
m.start();
Thread.sleep(1000); // Here comes the BIG question -> how to avoid these
// manually created pauses
Count c;
Thread t;
// Creating new threads for each row of the matrix
for (int i = 0; i < Matrix.matr.length; i++) {
c = new Count(i);
t = new Thread(c);
t.start();
}
//Again - the same question
System.out.println("Main - Sleep!");
Thread.sleep(50);
System.out.println("\t\t\t\t\tMain - Alive!");
int sum = 0;
for (int i = 0; i < Count.encounters.length; i++) {
System.out.println(i + "->" + Count.encounters[i]);
sum += Count.encounters[i];
}
System.out.println("Total numbers of digits: " + sum);
}
}
class Count implements Runnable {
int row;
public static int[] encounters = new int[10]; // here I store the number of each digit's(array's index) encounters
public Count(int row) {
this.row = row;
}
public synchronized static void increment(int number) {
encounters[number]++;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + ", searching in row " + row + " STARTED");
for (int col = 0; col < Matrix.matr[0].length; col++) {
increment(Matrix.matr[row][col]);
}
try {
Thread.sleep(1); // If it's missing threads are starting and stopping consequently
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + " stopped!");
}
}
class Matrix extends Thread {
static int[][] matr;
public Matrix(int[][] matr) {
Matrix.matr = matr;
}
#Override
public void run() {
//print();
fill();
System.out.println("matrix filled");
print();
}
public static void fill() {
for (int i = 0; i < matr.length; i++) {
for (int j = 0; j < matr[0].length; j++) {
matr[i][j] = (int) (Math.random() * 10);
}
}
}
public static void print() {
for (int i = 0; i < matr.length; i++) {
for (int j = 0; j < matr[0].length; j++) {
System.out.print(matr[i][j] + " ");
}
System.out.println();
}
}
}
P.S. I'm sorry if this question is too stupid for you to answer, but I'm a newbie in Java programming, as well as it's my very first post in stackoverflow, so please excuse me for the bad formatting, too :)
Thank you in advance!
Change the Thread.sleep by m.join()
Doing this will make the main thread wait for the other to complete its work and then it will continu its execution.
Cheers
To answer your main question:
Thread.join();
For example:
public static void main(String[] args) throws Exception {
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Do stuff");
}
});
t.start();
t.join();
}
The start call, as you know, kicks off the other Thread and runs the Runnable. The join call then waits for that started thread to finish.
A more advanced way to deal with multiple threads is with an ExecutorService. This detaches the threads themselves from the tasks they do. You can have a pool of n threads and m > n tasks.
Example:
public static void main(String[] args) throws Exception {
final class PrintMe implements Callable<Void> {
final String toPrint;
public PrintMe(final String toPrint) {
this.toPrint = toPrint;
}
#Override
public Void call() throws Exception {
System.out.println(toPrint);
return null;
}
}
final List<Callable<Void>> callables = new LinkedList<>();
for (int i = 0; i < 10; ++i) {
callables.add(new PrintMe("I am " + i));
}
final ExecutorService es = Executors.newFixedThreadPool(4);
es.invokeAll(callables);
es.shutdown();
es.awaitTermination(1, TimeUnit.DAYS);
}
Here we have 4 threads and 10 tasks.
If you go down this route you probably need to look into the Future API to so that you can check whether the tasks completed successfully. You can also return a value from the task; in your case a Callable<Integer> would seem to be appropriate so that you can return the result of your calculation from the call method and gather up the results from the Future.
As other Answers have stated, you can do this simply using join; e.g.
Matrix m = new Matrix(a);
m.start();
m.join();
However, I just want to note that if you do that, you are not going to get any parallelism from the Matrix thread. You would be better of doing this:
Matrix m = new Matrix(a);
m.run();
i.e. executing the run() method on the main thread. You might get some parallelism by passing m to each "counter" thread, and having them all join the Matrix thread ... but I doubt that it will be worthwhile.
Frankly, I'd be surprised if you get a worthwhile speedup for any of the multi-threading you are trying here:
If the matrix is small, the overheads of creating the threads will dominate.
If the matrix is large, you are liable to run into memory contention issues.
The initialization phase takes O(N^2) computations compared with the parallelized 2nd phase that has N threads doing O(N) computations. Even if you can get a decent speedup in the 2nd phase, the 1st phase is likely to dominate.

Categories