CopyOnWriteArrayList concurrent access problem on removing - java

I am struggling to find how to remove an Element of a CopyOnWriteAccess without getting a thread exception.
Exception in thread "Thread-3649" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at java.base/java.util.concurrent.CopyOnWriteArrayList.elementAt(CopyOnWriteArrayList.java:386)
at java.base/java.util.concurrent.CopyOnWriteArrayList.remove(CopyOnWriteArrayList.java:479)
at com.mycompany.playmatehunter.Downloader.init(Downloader.java:28)
at com.mycompany.playmatehunter.Downloader.run(Downloader.java:19)
at java.base/java.lang.Thread.run(Thread.java:834)
I have the following Downloader class
public class Downloader extends Thread{
private CopyOnWriteArrayList<String> url_list;
private String chemin;
public Downloader( CopyOnWriteArrayList<String> l, String chemin)
{
this.url_list = l;
this.chemin = chemin;
}
public void run()
{
init();
}
public synchronized void init() // the list is already synchronized
{
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}
And inside the main :
CopyOnWriteArrayList<String> index = new CopyOnWriteArrayList( FileToList("/index/index.txt") );
while( index.size() != 0)
{
List<Thread> tg = new ArrayList<Thread>();
for(int i=0;i<7;i++)
{
Thread t=new Thread(new Downloader(index, ""));
t.start();
tg.add(t);
}
for(Thread t: tg)
t.join();
}
Do you know how to get rid of ThreadException?
Thank you

Your access to the list is not synchronized. You have multiple threads, and even though the init() method is synchronized, the synchronization is on the thread instance, not on a common object, so it is useless. If you need to ensure mutual exclusion among threads, you have to synchronize on a common object:
public void init() // No synchronization here
{
synchronized(url_list) { // synchronize on a common object
if (!url_list.isEmpty())
{
int alea = (int)(Math.random()*url_list.size());
System.out.println(this.getName()+"removes the link nbr "+url_list.get(alea));
url_list.remove(alea);
}
}
}

Related

Print 1-1000 with two threads (even and odd) from the same class

So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}

Synchronized methods to avoid deadlock

I have two synchronized methods and I'm using the mediator design pattern.
I'm trying to avoid deadlocks, which is (from what I understand) for example when a thread has a lock on a variable res1 but needs a lock on variable res2. The other thread needs the lock for res1 but has the lock for res2 - resulting in a deadlock, right?
Assuming my understanding of deadlocks are correct, then my question is whether or not I have solved the issue of deadlock in this code?
I have two synchronized methods and two threads.
public class Producer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
public Producer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = (int)(Math.random()*100);
med.storeMessage(num);
System.out.println("P-" + id + ": " + num);
}
}
}
public class Consumer extends Thread {
private Mediator med;
private int id;
private static int count = 1;
// laver kopling over til mediator
public Consumer(Mediator m) {
med = m;
id = count++;
}
public void run() {
int num;
while(true) {
num = med.retrieveMessage();
System.out.println("C" + id + ": " + num);
}
}
}
public class Mediator {
private int number;
private boolean slotFull = false;
public synchronized void storeMessage(int num) {
while(slotFull == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = true;
number = num;
notifyAll();
}
public synchronized int retrieveMessage() {
while(slotFull == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
slotFull = false;
notifyAll();
return number;
}
}
public class MediatorTest {
public static void main(String[] args) {
Mediator mb = new Mediator();
new Producer(mb).start();
new Producer(mb).start();
new Producer(mb).start();
new Consumer(mb).start();
new Consumer(mb).start();
}
}
for example when a thread has a lock on a variable res1 but needs a lock on variable res2
What matters is not that there are two variables, what matters is that there must be two (or more) locks.
The names "res1" and "res2" are meant to suggest two resources each of which may have one or more variables, and each of which has its own lock. Here's where you get into trouble:
final Object lock1 = new Object();
final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
// Call Thread.sleep(1000) here to simulate the thread losing its time slice.
synchronized(lock2) {
doSomethingThatRequiresBothLocks
}
}
}
public void method2() {
synchronized (lock2) {
// Do the same here 'cause you can't know which thread will get to run first.
synchronized(lock1) {
doSomethingElseThatRequiresBothLocks()
}
}
}
If thread A calls method1(), there is a very small chance that it could lose its time slice (i.e., turn to run) just after it successfully locks lock1, but before it locks lock2.
Then, while thread A is waiting its turn to run again, thread B calls method2(). Thread B will be able to lock lock2, but then it gets stuck because lock1 is locked by thread A. Furthermore, when thread A gets to run again, it will immediately be blocked when it tries to lock lock2 which is owned by thread B. Neither thread will ever be able to continue from that point.
In real code, it's never so obvious. When it happens in real-life, it usually is because of some unforseen interaction between code from two or more different modules that may not even be aware of each other, but which access the same common resources.
Your understanding of the basic deadlock problem is correct. With your second question about validity of your solution to the deadlock problem, you've only got 1 lock, so I'd say "yes" by default, since the deadlock you described isn't possible in this situation
I agree with what #ControlAltDel has said. And your understanding of a deadlock matches mine. Whereas there are a few different ways in which a deadlock can manifest itself, the way you describe -- inconsistently acquiring multiple monitors by involved threads (methods) causes deadlock.
Another way would be to (for example,) sleep while holding a lock. As you coded correctly, when the producer finds that slotFull = true, it waits, giving up the lock, so the other thread (consumer, which is sharing the same instance of Mediator with producer) can make progress potentially causing this thread also to make progress after it gets a notification. If you had chosen to call Thread.sleep() instead (naively hoping that someone will cause the sleep to end when the condition would be false), then it would cause a deadlock because this thread is sleeping, still holding the lock, denying access to the other thread.
Every object has one lock which restrict multiple threads to access same block of code or method when you use synchronized keyword.
Coming to your problem, it will not deadlock.
If you have two independent attribute in a class shared by multiple threads, you must synchronized the access to each variable, but there is no problem if one thread is accessing one of the attribute and another thread accessing the other at the same time.
class Cinema {
private long vacanciesCinema1; private long vacanciesCinema2;
private final Object controlCinema1, controlCinema2;
public Cinema() {
controlCinema1 = new Object();
controlCinema2 = new Object();
vacanciesCinema1 = 20;
vacanciesCinema2 = 20;
}
public boolean sellTickets1(int number) {
synchronized (controlCinema1) {
if (number < vacanciesCinema1) {
vacanciesCinema1 -= number;
return true;
} else {
return false;
}
}
}
public boolean sellTickets2(int number) {
synchronized (controlCinema2) {
if (number < vacanciesCinema2) {
vacanciesCinema2 -= number;
return true;
} else {
return false;
}
}
}
public boolean returnTickets1(int number) {
synchronized (controlCinema1) {
vacanciesCinema1 += number;
return true;
}
}
public boolean returnTickets2(int number) {
synchronized (controlCinema2) {
vacanciesCinema2 += number;
return true;
}
}
public long getVacanciesCinema1() {
return vacanciesCinema1;
}
public long getVacanciesCinema2() {
return vacanciesCinema2;
}
}
class TicketOffice1 implements Runnable {
private final Cinema cinema;
public TicketOffice1(Cinema cinema) {
this.cinema = cinema;
}
#Override
public void run() {
cinema.sellTickets1(3);
cinema.sellTickets1(2);
cinema.sellTickets2(2);
cinema.returnTickets1(3);
cinema.sellTickets1(5);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
cinema.sellTickets2(2);
}
}
public class CinemaMain {
public static void main(String[] args) {
Cinema cinema = new Cinema();
TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
Thread thread1 = new Thread(ticketOffice1, "TicketOffice1");
TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
Thread thread2 = new Thread(ticketOffice2, "TicketOffice2");
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Room 1 Vacancies: %d\n", cinema.getVacanciesCinema1());
System.out.printf("Room 2 Vacancies: %d\n", cinema.getVacanciesCinema2());
}
}

Synchronized method does not work as expected

I have a variable which is shared by two threads. The two threads will do some operations on it. I don't know why the result of sharedVar is different every time I execute the program.
public class Main
{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedInt); // I expect this value to be 20000, but it's not
}
}
The following is the class "MyThread"
public class MyThread extends Thread
{
private int times = 10000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
#Override
public void run()
{
addOne();
}
}
The final result of sharedVar sometimes are 13735, 12508, or 18793; but never 20000, which is the result I expect. Another interesting thing about the program is when times=1000. I always get 2000 as the final result.
Can anyone explain this phenomenon?
A synchronized method protects the resource this that means that your code is equivalent to:
private void addOne()
{
synchronized(this)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
But you have 2 objects for which addOne method is called. That means this for mt1.addOne is not the same than this for mt2.addOne and therefore you don't have a common resource of synchronization.
Try changing yout addOne code to:
private void addOne()
{
synchronized(MyThread.class)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
And you will observe the expected behaviour. As the comments below suggest, it is better to use a different object than MyThread.class for synchronization since class objects are accesible from many points and it is easy that other code may try to synchronize using the same object.
When you use synchronized on non-static method, you use current object as monitor.
When you use synchronized on static method, you use current object of class (ClassName.class static field) as monitor.
In your case, you use synchronized on Thread's object (2 different instances), so two different threads will modify your sharedVar static field at same time.
You can fix it in different ways.
Move addOne method to Main and make it static.
private static synchronized void addOne(int times)
{
for (int i = 0; i < times; ++i)
{
sharedVar++;
}
}
Or you can create class called SharedVar with field private int var; and method synchronized void addOne(int times) and pass single instance of SharedVar to your treads.
public static void main(String[] args)
{
SharedVar var = new SharedVar();
MyThread mt1 = new MyThread(var);
MyThread mt2 = new MyThread(var);
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(var.getVar()); // I expect this value to be 20000, but it's not
}
But if you need only one integer to be changed in multiple threads, you can use classes from java.til.concurrent.*, like AtomicLong or AtomicInteger.
Define sharedVar as an AtomicLong instead of int. Making the function synchronized works as well but it is less efficient because you only need the increment to be synchronized.
When a thread is about to execute a 'synchronized' instance method, it aqcuires the lock on the Object(to be precise, lock on that object monitor).
So in your case, Thread mt1 acquires lock on Object mt1 and Thread mt2 acquires lock on Object mt2 and they do not block each Other as the two threads are working on two different locks.
And when two threads modify a shared variable concurrently(not synchronized way), the result is unpredictable.
Well about the case of value 1000, for smaller inputs the interleaved execution might have resulted in correct result(luckily).
Sol : remove the synchronized keyword from addOne method and make sharedVal as type of 'AtomicInteger'
Join the thread immediately after start method. From this thread-1 will start and go to dead state after that thread-2 will start and go to dead state. So it will print your expected output always.
Change the code as shown below:-
public class Main{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
try
{
mt1.start();
mt1.join();
mt2.start();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedVar);
}
}
class MyThread extends Thread
{
private int times = 1000000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar++;
}
}
#Override
public void run()
{
addOne();
}
}

Using two threads and controlling one from the other in java?

Can someone please help me out.
I need to use two threads in a way that one thread will run permanently while(true) and will keep track of a positioning pointer (some random value coming in form a method). This thread has a logic, if the value equals something, it should start the new thread. And if the value does not equal it should stop the other thread.
Can someone give me some code snippet (block level) about how to realize this?
Create a class that implements Runnable. There you'll make a run() method.
Like:
public class StackOverflow implements Runnable{
private Thread t = null;
public void run(){
}
public void setAnotherThread(Thread t){
this.t = t;
}
}
On the main class, you'll create 2 instances of Thread based on the other class you created.
StackOverflow so1 = new StackOverflow();
StackOverflow so2 = new StackOverflow();
Thread t1 = new Thread(so1);
Thread t2 = new Thread(so2)
Then you set one thread in the other, so you can control it.
t1.setAnotherThread(so2);
t2.setAnotherThread(so1);
Then you do what you need to do.
Ok if I'm not mistaken, you want to have one class that could be run as a "Thread" or as a (lets call it) a "sub-Thread".
But how to do that with one run method? just declare a boolean variable that specifies whether the thread object is a sub-thread or a parent thread, and accordingly declare two constructors, one would create a parent thread and the other would create a sub thread, and to be able to stop the sub-thread declare another variable called stop that is default to false.
class ThreadExample extends Thread {
private boolean sub = false;
private ThreadExample subThread = null;
public boolean stop = false;
public ThreadExample() {
}
public ThreadExample(boolean sub) {
this.sub = sub;
}
public void run() {
if (sub) {
runSubMethod();
} else {
runParentMethod();
}
}
public void runParentMethod() {
boolean running = true;
while (running) {
if (getRandomValue() == some_other_value) {
if (getSubThread().isAlive()) {
continue;
}
getSubThread().start();
} else {
getSubThread().makeStop();
}
}
}
public void runSubMethod(){
while(true){
//do stuff
if (stop)
break;
}
}
public int getRandomValue() {
//your "Random Value"
return 0;
}
private ThreadExample getSubThread() {
if (subThread == null) {
subThread = new ThreadExample(true);
}
return subThread;
}
public void makeStop(){
stop = true;
}
}
Here is a simple idea how you can implement as many threads as you like in a class:
class MultipleThreads{
Runnable r1 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//-----
Runnable r2 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//--- continue as much you like
public static void main (String[] args){
Thread thr1 = new Thread(r1);
Thread thr2 = new Thread(r2);
thr1.start();
thr2.start();
}
}
Hope it helps!!
For communicating between the two threads, one simple solution is to set a boolean type volatile static variable, and have it set from one thread and put it in while(flag) condition in the other thread.
You can control the other thread using this method.
And if you have waiting processes or Thread.sleep() and you want to break the thread without having it to finish it, your interrupts by catching the exception.

IlleagalMonitorStateException when I am trying to run this program

public class ThreadTest
{
public static Integer i = new Integer(0);
public static void main(String[] args) throws InterruptedException
{
ThreadTest threadTest = new ThreadTest();
Runnable odd = threadTest.new Numbers(1, "thread1");
Runnable even = threadTest.new Numbers(0, "thread2");
((Thread) odd).start();
((Thread) even).start();
}
class Numbers extends Thread
{
int reminder;
String threadName;
Numbers(int reminder, String threadName)
{
this.reminder = reminder;
this.threadName = threadName;
}
#Override
public void run()
{
while (i < 20)
{
synchronized (i)
{
if (i % 2 == reminder)
{
System.out.println(threadName + " : " + i);
i++;
i.notify();
}
else
{
try
{
i.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
}
You can't synchronize on i because it changes during execution of your program.
Since Integer in Java is immutable, after executing i++ i will contain a reference to another object, not the object you have synchronized on. So, you can't call wait()/notify() on this new object, because these methods may be only called on the object you are synchronized on, otherwise you get IllegalMonitorStateException.
You need to synchronize on some other object that doesn't change during execution. For example, you may create a separate object for this purpose:
public class ThreadTest {
public static Integer i = new Integer(0);
public static Object lock = new Object();
...
class Numbers extends Thread {
...
#Override
public void run() {
...
synchronized (lock) {
...
lock.notify();
...
lock.wait();
...
}
}
}
}
This line:
i++;
is equivalent to:
i = i + 1;
which (due to autoboxing) becomes something like:
i = new Integer(i.intValue() + 1);
So, when you call i.notify() you are synchronized on the old i, not the new one.
I'd suggest changing i into an ordinary int variable, and create a separate object to synchronize on:
static int i = 0;
static Object iMonitor = new Object();
As documentation states the exception is thrown when
the current thread is not the owner of the object's monitor
It also states that
This method should only be called by a thread that is the owner of this object's monitor.
And this condition can be obtained by
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
You could try calling the wait method from inside the class that uses i. This could be done by extending the class and writing two new methods for notify and wait..
You cannot put wait() and notify() in the same synchronized block because that will just cause a deadlock. Make sure only the wait and notify functions are wrapped with a synchronized block like this:
synchronized (i) {
i.wait(); // or i.notify();
}

Categories

Resources