Why do I need to synchronize this variable - java

I have 4 threads each trying to find the max value in a linked list.
This is my thread class:
public class MyThread extends Thread {
LinkedList<Integer> list;
int max = Integer.MIN_VALUE;
public MyThread(LinkedList<Integer> list) {
this.list = list;
}
public void run() {
synchronized (list) { /* If I don't synchronize list, I get a NoSuchElementException at list.remove() */
while (!list.isEmpty()) {
int num = list.remove();
if (num > max) {
max = num;
}
}
}
}
}
And here is the class with the main method:
public class Application {
public static void main(String args[]) throws InterruptedException {
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
MyThread t1 = new MyThread(list);
MyThread t2 = new MyThread(list);
MyThread t3 = new MyThread(list);
MyThread t4 = new MyThread(list);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(t1.max);
System.out.println(t2.max);
System.out.println(t3.max);
System.out.println(t4.max);
}
}
In the above code, I have to synchronize the list variable within the run method or else I'll get a NoSuchElementException at list.remove(). Why is this the case?
Doesn't each thread have it's own list so there is no thread interference?
Thanks

I will address a different part of your question that #Rishi addressed:
Doesn't each thread have it's own list so there is no thread interference?
The simple answer is: No, it does not. In Java, when you pass an object of class type to a constructor or method, you aren't passing the obejct itself but rather a pointer to it. If you want to pass a separate copy of the linked list to each thread, you need to use LinkedList#Clone.
If you use clone, then when a thread removes one integer from its linked list, it will not be removed from the other linked lists. To properly paralellize this, you should use a standard array with all of your numbers and assign a segment of this array to each thread (ie. thread 1 does 0-9, thread 2 does 10-19, thread 3 does 20-29, etc.). The array's contents will be visible to any threads created after the contents are deposited in the array.
I should also note that you should not extend Thread. Instead, extend Runnable and pass it to a thread. Furthermore, an array(list) would be better than 4 separate variables as it allows you to easily change the number of threads later.

LinkedList is not thread-safe. Hence it would need external synchronization if you operate on LinkedList with more than one thread.
You can use BlockingQueue, whose poll() method would come handy in this case.

Related

How to create a blocking thread-safe Stream in Java?

I want to create a java.util.stream.Stream that blocks on terminal actions and uses an arbitrary object for synchronization. The Stream's methods must do so themselves in a transparent way such that I could safely pass the Stream to code that is not aware of the synchronization.
Consider the following example:
void libraryMethod(Stream<Whatever> s) {
for (int i = 0; i < 10000000; ++i) { /* ... */ }
s.filter(Library::foo).forEach(Library::bar);
}
/* Elsewhere in my code */
Set<Whatever> aSet = Collections.synchronizedSet(...);
/* ... */
libraryMethod(new MyBlockingStream<>(set.stream(), set));
Before performing forEach, I want aSet's lock to be acquired by the MyBlockingStream itself and released only when forEach terminates. This should guarantee that I don't get ConcurrentModificationExceptions because other threads might want to modify the set. I can't use synchronized (aSet) on the entire libraryMethod because that would block aSet for much longer then needed.
Is it possible to do this? If so, are there any existing implementations that do that or do I have to write it myself?
Note: this question has nothing to do with how the Stream performs the actions - I don't care whether it's parallel or not. I am aware that there exist intrinsically unsynchronizable iterator() and spliterator() methods. I don't care about them either.
You could use a lock.
public class Example {
public static ReentrantLock lock = new ReentrantLock();
private static void sleep() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static Runnable createRunnable() {
return () -> {
try {
Arrays.asList("a", "b", "c").stream().forEach(e -> {
if (!lock.isHeldByCurrentThread())
lock.lock();
sleep();
System.out.println(String.format("thread %s with element %s", Thread.currentThread().getId(), e));
});
} finally {
if(lock.isHeldByCurrentThread())
lock.unlock();
}
};
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(createRunnable());
Thread t2 = new Thread(createRunnable());
Thread t3 = new Thread(createRunnable());
t1.start();
t2.start();
t3.start();
System.out.println("join all threads");
t1.join();
t2.join();
t3.join();
}
}
The thread first to reach forEach will lock up all other threads.
Output in this case is
join all threads
thread 16 with element a
thread 16 with element b
thread 16 with element c
thread 15 with element a
thread 15 with element b
thread 15 with element c
thread 14 with element a
thread 14 with element b
thread 14 with element c
EDIT 1
As #Holger pointed out this will not work if the stream get nested. The inner stream will release the lock too early.
Here is what I ended up doing: https://gist.github.com/OLEGSHA/bda28ffaa4b24e64b94a8c30c3ad9b0c. These Stream wrappers synchronize all terminal operations using a provided object and wrap streams from intermediate operations.
This is essentially
public void forEach(Consumer<? super T> action) {
synchronized (monitor) {
parent.forEach(action);
}
}
for every terminal operation in Stream interface. IntStream, LongStream and DoubleStream versions included.
I think there must be a better solution though.

Why Unsynchronized ArrayList Object add method is not behaving properly

Here is the sample code
1) ArrayList is a single object which is passed to every thread of ThreadPool.
2) At end of execution list size should be 50, if you check the sample outputs its may not 50. Sometime it may be 41 or 47 like that, why it is behaving like that.
public class Test {
ArrayList list=new ArrayList();
public static void main(String[] args) {
ExecutorService executorService3 = Executors.newScheduledThreadPool(10);
Test test=new Test();
for(int i=0;i<5;i++)
{
Mythread t1=new Mythread(test.list);
executorService3.execute(t1);
}
executorService3.shutdown();
while(executorService3.isShutdown())
{
//---This is not giveging proper output as expected is 50.--
System.out.println("List size="+test.list.size());
break;
}
}
}
class Mythread implements Runnable {
List list=null;
Mythread(List list) {
this.list=list;
}
#Override
public void run() {
for(int i=0;i<10;i++) {
this.list.add(i);
}
}
}
Your code isn't waiting for the threads to finish execution. By the time your code calls the following line
System.out.println("List size="+test.list.size());
there's no guarantee that they have finished, and so no guarantee that the list contains the expected 50 items. Use the awaitTermination method (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit)), e.g.:
executorService3.shutdown();
executorService3.awaitTermination(1, TimeUnit.SECONDS);
System.out.println("List size="+test.list.size());
(Exception handling omitted for brevity)
As it says in the Javadoc for ArrayList:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
So it's "not behaving properly" because you're not using it as described in the documentation.
As is suggested in the Javadoc, you can wrap your list in a synchronized list:
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
It's a concurrency problem.
The way i see it, you have :
5 threads that will execute the run method on the same object. Multiple threads can insert a variable, on the same position in the array list, since it is not synchronized.
Could you print the content of your list ?

How do I make sure a line of code runs only once for each individual thread?

I have a few threads running simultaneously, and whenever each starts, I would like each individual to get one item from the String Arraylist, and hold onto that particular unique item until it completes. What would be a good way to implement this? In the run method in a thread, I though about String uniqueItem = itemList.get(k); and k++ after getting it, but the thread will run that particular line over and over, and the next time it runs it again, it will be holding onto a different unique item. Is there a way to make each thread get one item only once, and the next gets what's available, and so on, and hold onto that one item.
ItemHolder thread = new ItemHolder();
private ArrayList<String> itemList = new ArrayList<String>(); //Contains 4 Strings (e.g. Apple, Orange, Watermelon, Pear)
int k = 0;
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
class ItemHolder extends Thread{
public void run(){
String uniqueItem = itemList.get(k); //Would like the first thread to grab the first index item, 0, and hold onto it until it finishes. But other thread that runs the same, I would like it to have index item, 1, and hold onto that, and the other thread to have whatever is available and so on.
k++; //This would be a problem
}
}
You should use a java.util.concurrent.BlockingQueue instead, as ArrayList is not thread safe.
Example code:
public class ItemHolderDemo {
public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.add("a");
queue.add("b");
Runnable thread = new ItemHolder(queue);
ExecutorService executor = Executors.newFixedThreadPool(4); //E.g. run 4 Threads
executor.execute(thread);
}
static class ItemHolder extends Thread {
BlockingQueue<String> queue;
public ItemHolder(BlockingQueue<String> queue) {
this.queue = queue;
}
public void run() {
String uniqueItem = null;
// use while loop in case there is an interruption
while (uniqueItem == null) {
try {
// use queue.poll() with break statements if you want a timed wait
uniqueItem = queue.take();
} catch (InterruptedException e) {
}
}
// got item
System.out.println(uniqueItem);
}
}
}
You are using ExecutorService. This means that you do not need to pass thread instance, but a Runnable would suffice.
Having said that, you will be creating Runnable instances, and passing them to the ExecutorService in some kind of loop. You can maintain the state of each Runnable in a local field, where you can store the index on which that Runnable instance is operating on.
You would check, if your runnable's state is not set, then set it to the element that the Runnable would operate upon. If the state is already set, then do nothing.
You want to avoid the scenario where two threads execute the get() at the same time then increment k at the same time. To achieve that, you have to ensure k is incremented atomically by each thread. You can use AtomicInteger to do just that.
private ArrayList<String> itemList = new ArrayList<String>();
AtomicInteger a = new AtomicInteger();
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i=0; i<itemList.size(); i++) { // I assume itemList will not be modified
ItemHolder thread = new ItemHolder();
executor.execute(thread);
}
class ItemHolder extends Thread{
public void run(){
int k = a.getAndAdd(1);
String uniqueItem = itemList.get(k);
// Some lengthy processing might occur here...
}
}

Java Thread synchronization - printing out numbers in right order

I'm learning how to work with threads in Java and I need some advice..
I want to print on the standard output numbers from 0..50 with the name of the thread that has done it using three threads.
I have two classes - class Counter that implements Runnable and class Main that creates and runs the threads. Counter has the variable c which is shared among the threads.
My idea was, that I increment c by 1 and then call yield() on the current thread so as the other threads would do the same. Repeat this until c reaches 50.
But it doesen't work, the numbers are printed out in wrong order. How do I fix this?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
#Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
Edit: In the end I solved it this way. Thank you all who helped me with the tough start with multithreading.
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
#Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
Use syncrhonized section in method increment with special static object.
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
Or make this method synchronized via its declaration.
But it's wrong idea to store your real data in thread objects. Thread should just to manipulate with share objects but not to store them.\
And actually I don't understand why do you start thread in
Quoting from the javadoc Thread.yield(), emphasis by me:
public static void yield()
A hint to the scheduler that the
current thread is willing to yield its
current use of a processor. The
scheduler is free to ignore this
hint.
...
It is rarely appropriate to use
this method.
Make increment() synchronized in order to prevent other threads from entering the method concurrently.
In conjunction with yield() you should be able to get another thread print the next number (not always since the system might resume the thread that called yield again - see Ingo's answer - , but the order should still be the same).
synchronized increment() would mean that any thread that tries to enter that method on the same object would have to wait if another thread would have aquired the lock already by entering the method.
Yes your code won't work. Thread#yield() won't control the thread scheduler in the manner you desire. I"m curious what result you get. You'll probably get repeated numbers and some number that are slightly out of order.
You could use atomic integer which should remove all duplicates. But since the print statement is not atomic. You may still print your results out of order. So you should probably just synchronize the increment method. Also you don't really need yield so dump it.
If the purpose of the problem is to go from thread 1 to thread 2 to thread 3 back to thread 1, etc... Such that the results are
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
Then you'll need to lock the increment method and use wait and notifyAll. wait will cause other threads to halt processing until the current thread notifies them to start again.

Data race in Java ArrayList class

I was reading about CopyOnWriteArrayList and was wondering how can I demonstrate data race in ArrayList class. Basically I'm trying to simulate a situation where ArrayList fails so that it becomes necessary to use CopyOnWriteArrayList. Any suggestions on how to simulate this.
A race is when two (or more) threads try to operate on shared data, and the final output depends on the order the data is accessed (and that order is indeterministic)
From Wikipedia:
A race condition or race hazard is a flaw in an electronic system or process whereby the output and/or result of the process is unexpectedly and critically dependent on the sequence or timing of other events. The term originates with the idea of two signals racing each other to influence the output first.
For example:
public class Test {
private static List<String> list = new CopyOnWriteArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(5);
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.execute(new WriterTask());
e.awaitTermination(20, TimeUnit.SECONDS);
}
static class WriterTask implements Runnable {
#Override
public void run() {
for (int i = 0; i < 25000; i ++) {
list.add("a");
}
}
}
}
This, however, fails when using ArrayList, with ArrayIndexOutOfbounds. That's because before insertion the ensureCapacity(..) should be called to make sure the internal array can hold the new data. And here's what happens:
the first thread calls add(..), which in turn calls ensureCapacity(currentSize + 1)
before the first thread has actually incremented the size, the 2nd thread also calls ensureCapacity(currentSize + 1).
because both have read the initial value of currentSize, the new size of the internal array is currentSize + 1
the two threads make the expensive operation to copy the old array into the extended one, with the new size (which cannot hold both additions)
Then each of them tries to assign the new element to array[size++]. The first one succeeds, the second one fails, because the internal array has not been expanded properly, due to the rece condition.
This happens, because two threads have tried to add items at the same time on the same structure, and the addition of one of them has overridden the addition of the other (i.e. the first one was lost)
Another benefit of CopyOnWriteArrayList
multiple threads write to the ArrayList
a thread iterates the ArrayList. It will surely get ConcurrentModificationException
Here's how to demonstrate it:
public class Test {
private static List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
ExecutorService e = Executors.newFixedThreadPool(2);
e.execute(new WriterTask());
e.execute(new ReaderTask());
}
static class ReaderTask implements Runnable {
#Override
public void run() {
while (true) {
for (String s : list) {
System.out.println(s);
}
}
}
}
static class WriterTask implements Runnable {
#Override
public void run() {
while(true) {
list.add("a");
}
}
}
}
If you run this program multiple times, you will often be getting ConcurrentModificationException before you get OutOfMemoryError.
If you replace it with CopyOnWriteArrayList, you don't get the exception (but the program is very slow)
Note that this is just a demonstration - the benefit of CopyOnWriteArrayList is when the number of reads vastly outnumbers the number of writes.
Example:
for (int i = 0; i < array.size(); ++i) {
Element elm = array.get(i);
doSomethingWith(elm);
}
If another thread calls array.clear() before this thread calls array.get(i), but after it has compared i with array.size(), -> ArrayIndexOutOfBoundsException.
Two threads, one incrementing the arraylist and one decrementing. Data race could happen here.

Categories