I'm studying concurrency at the moment and I was learning about blocking threads.
I know that a thread can come to a blocked state when the corresponding attached task tries to access a method that is locked because another thread acquired the lock.
So from what I've read the task blocks and wait until it can access that method and so goes on with its business (namely, the rest of the run() method).
So why does this code exits like the task could call syn.getI() and access the variable in an "erroneous" state (even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI() ) ? where am I wrong on this?
public class SynchronizedClass {
private int i;
private boolean flag=true;
public SynchronizedClass(int i){
this.i=i;
}
public int getI(){
return i;
}
public boolean getFlag(){
return flag;
}
public synchronized void manipulate(){
i=(i*2)+1; //odd number
Thread.yield();
i= i+1; //even number
}
public void close(){
flag=false;
}
}
public class MyThread implements Runnable {
//auto-managed runnable
Thread t;
SynchronizedClass syn;
public MyThread(SynchronizedClass syn){
this.syn=syn;
t=new Thread(this);
t.start();
}
#Override
public void run() {
while(syn.getFlag()==true){
syn.manipulate();
if (syn.getI()%2!=0){
syn.close();
System.out.println("exit");
}
}
}
public static void main(String[] args) {
SynchronizedClass syn = new SynchronizedClass(1);
for(int i=0;i<4;++i)
new MyThread(syn);
}
}
even if the syn.manipulate() method is locked so I'm assuming the task cannot get to calling getI()
That's the mistake you're making, I believe.
Just because one method is synchronized doesn't implicitly mean that anything else is synchronized. It's not like one thread owning the monitor associated with an object stops other threads from accessing that object - it just stops other threads from acquiring the monitor.
If you make the getI() method synchronized, then one thread owning the monitor due to manipulate() means that other threads calling getI() on the same object would have to wait, in order to acquire the monitor.
Related
I was looking for a way to make one thread wait/sleep until another thread signalled that something was ready. The waiting thread should wake up, process the data that was made available, then go back to sleep until the other thread signalled again.
The simplest method I could find was Object.wait() and Object.notify(), which behaved like a semaphore initialised to value 0. However, without the synchronized statements around notify/wait, Java always threw IllegalMonitorStateException when the thread was not the monitor owner. So I simply put them around the code like shown below.
THREAD 1: running infinite loop
public class Main {
private Handler handler; // only one instance (singleton pattern)
public void listen() {
while (true) {
try {
synchronized (handler) {
handler.wait();
int value = handler.getSize();
// do something
}
} catch (InterruptedException e) {
// ...
}
}
}
}
THREAD 2: Some other class calls removeItem
public class Handler {
// SINGLETON PATTERN - ONLY ONE INSTANCE
private ArrayList<Integer> sharedList;
private Handler() {
sharedList = new ArrayList<>();
}
public void addItem(Integer i) {
synchronized (sharedList) {
// add to list
}
}
public void removeItem(int i) {
synchronized (sharedList) {
// remove item
// notify that something is removed
synchronized (this) {
this.notify(); // this == handler
}
}
}
public int getSize() {
synchronized (sharedList) {
return sharedList.size();
}
}
}
It seems to work perfectly fine but not sure if there is a hidden bug.
My question is: Is this safe? Does wait release the instance lock for handler/this so notify can acquire the lock?
Synchronized blocks are safe. The statement synchronized(obj) acquires the lock of the argument obj, so you can call wait and notify on it. They both require that the current thread holds the lock on the object.
You have to be careful about the double-locking you have in removeItem where you lock two objects. If you ever need this, you have to make sure that you always lock them in the same order, otherwise, you may create a deadlock.
In my current assignment, we are to use a Semaphore to synchronize access to critical sections. However, the provided implementation has me questioning whether it is properly implemented or not. I'd like someone to confirm my worries.
public class Semaphore {
private int iValue;
public Semaphore(int piValue) {
this.iValue = piValue;
}
public Semaphore() {
this(0);
}
public synchronized boolean isLocked() {
return (this.iValue <= 0);
}
public synchronized void P() {
try {
while(this.iValue <= 0) {
wait();
}
this.iValue--;
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void V() {
++this.iValue;
notifyAll();
}
}
I believe that there is a possibility for deadlock in this code:
Thread A calls P() and iValue is decremented to 0.
Thread B calls P() before thread A can call V(). The value of iValue is 0, so it enters the while loop.
Thread A now tries to call V(), but cannot because thread B holds the lock. Therefore, there is a deadlock.
Is my conclusion correct?
No.
When you wait the lock is released (you get it back when the wait is over).
Javadoc for wait:
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
i want to understand this:
String string;
public Test(String string){
this.string = string;
.....
}
public void foo(newObjectPerCall o) {
synchronized (o) {
//each thread can enter here because the object passed is always different
....
synchronized (string) {
// acquire this lock if the String is free.
}
}
}
public synchronized void function() {
}
public static void main(){
Test test = new Test("hello");
for(int i = 0; i < 10;i++){
WorkerThread workerThread = new WorkerThread(test);
workerThread.start();
}
}
thread class
public class WorkerThread extends Thread {
private Test test;
public WorkerThread(Test test) {
this.test = test;
}
#Override
public void run() {
while (true) {
test.foo(new Object());
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test.function();
}
}
}
my doubts are:
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes. They will block, waiting to acquire the monitor for string.
When on thread ,for some reasons, remains outside the foo function, can this one acquire the lock of test instance inside function?
Yes, it's entirely independent of the other monitors. A synchronized instance method is just equivalent to one whose body is
synchronized (this) {
...
}
If no other thread already owns the monitor for this, the "new" thread can acquire it regardless of what other monitors are owned. But as all your worker threads are using the same instance of Test, only one of them will be able to be "in" function() at a time. That can be at the same time as another thread is executing foo() though.
Sorry I know only the answer only for the first question
if one thread acquire the inner lock, other threads that acquired the outer lock, will remains inside the foo function?
Yes
Here I have an object with 2 threads and providing lock on object by print() but after some loop it losing lock and execute the second thread and it will change the value of breakLoop and first thread will be terminate.
public class ThreadLock {
public static void main(String[] args) {
Entity entity=new Entity();
RunnableClass runnable = new RunnableClass(entity);
Thread threadClass= new Thread(runnable);
Thread threadClass2= new Thread(runnable);
threadClass.setName("First Thread");
threadClass2.setName("Second Thread");
threadClass.start();
threadClass2.start();
}
}
class RunnableClass implements Runnable{
Entity entity;
public RunnableClass(Entity entity) {
this.entity=entity;
}
public void run(){
if(Thread.currentThread().getName().equalsIgnoreCase("First Thread"))
entity.print();
else{
entity.print("");
}
}
}
class Entity{
public void print(String str){
System.out.println("Non sysncronized method accessed by "+Thread.currentThread().getName());
breakLoop=false;
}
boolean breakLoop=true;
//lock will work for same object
public synchronized void print(){
System.out.println("Lock aquired by : "+Thread.currentThread().getName());
while (breakLoop) {
System.out.println("hhhhhhhhhhhhhh");
}
System.out.println("Lock released by : "+Thread.currentThread().getName());
}
}
The first thread having the lock doesn't stop the second thread from calling the Entity.print(String) method, because that method doesn't try to acquire the lock. Calling print(String) sets the breakLoop flag to false.
(When the flag value becomes visible to the other thread is not well-defined due to memory visibility issues --it would be better to make the breakLoop instance variable volatile-- but that doesn't necessarily mean the second thread will never see the change to the instance variable. Memory visibility issues are more apparent on some platforms than others.)
If you change the print(String) method to be synchronized, it will hang waiting for the first thread to finish.
class Downloader extends Thread {
private InputStream in;
private OutputStream out;
private ArrayList<ProgressListener> listeners;
public Downloader(URL url, String outputFilename) throws IOException {
in = url.openConnection().getInputStream();
out = new FileOutputStream(outputFilename);
listeners = new ArrayList<ProgressListener>();
}
public synchronized void addListener(ProgressListener listener) {
listeners.add(listener);
}
public synchronized void removeListener(ProgressListener listener) {
listeners.remove(listener);
}
private synchronized void updateProgress(int n) {
for (ProgressListener listener: listeners)
listener.onProgress(n);
}
public void run() {
int n = 0, total = 0;
byte[] buffer = new byte[1024];
try {
while((n = in.read(buffer)) != -1) {
out.write(buffer, 0, n);
total += n;
updateProgress(total);
}
out.flush();
} catch (IOException e) { }
}
}
The above code is from the book "seven concurrency models in seven weeks". The book says the above code is having potential for the deadlock as the the synchronized method updateProgress calls a alien method[onProgress] that might acquire another lock.
Since we acquire two locks without right order, the deadlock might occur.
Can anyone explain how the deadlock happens in the above scenario?
Thanks in advance.
It's best to make the objects you use with synchronized private.
Since you synchronize on the Downloader, you don't know whether other threads synchronize on the Downloader too.
The following listener causes a deadlock:
MyProgressListener extends ProgressListener {
public Downloader downloader;
public void onProgress(int n) {
Thread t = new Thread() {
#Override
public void run() {
synchronized(downloader) {
// do something ...
}
}
};
t.start();
t.join();
}
}
Code that deadlocks:
Downloader d = new Downloader(...);
MyProgressListener l = new MyProgressListener();
l.downloader = d;
d.addListener(l);
d.run();
The following will happen if you run that code:
the main thread reaches the updateProgress and aquires a lock on the Downloader
the MyProgressListener's onProgress method is called and the new thread t is started
the main thread reaches t.join();
In this situation the main thread cannot procede until t is finished, but for t to finish, the main thread would have to release it's lock on the Downloader, but that won't happen since the main thread can't procede -> Deadlock
First off, recall that the keyword synchronized, when applied to a a class, implies locking the whole object this method belongs to. Now, let's sketch out another couple of objects triggering the deadlock:
class DLlistener implements ProgressListener {
private Downloader d;
public DLlistener(Downloader d){
this.d = d;
// here we innocently register ourself to the downloader: this method is synchronized
d.addListener(this);
}
public void onProgress(int n){
// this method is invoked from a synchronized call in Downloader
// all we have to do to create a dead lock is to call another synchronized method of that same object from a different thread *while holding the lock*
DLthread thread = new DLThread(d);
thread.start();
thread.join();
}
}
// this is the other thread which will produce the deadlock
class DLThread extends Thread {
Downloader locked;
DLThread(Downloader d){
locked = d;
}
public void run(){
// here we create a new listener, which will register itself and generate the dead lock
DLlistener listener(locked);
// ...
}
}
One way to avoid the dead lock is to postpone the work done in addListener by having internal queues of listeners waiting to be added/removed, and have Downloader taking care of those by itself periodically. This ultimately depends on Downloader.run inner working of course.
Probably the problem in this code:
for (ProgressListener listener: listeners)
listener.onProgress(n);
When one thread, which holds a lock, calls an external method
like this one (onProgress) then you cannot guarantee that
implementation of this method won't try to obtain other lock,
which could be held by different thread. This may cause a deadlock.
Here's a classic example that shows the kind of hard-to-debug problems the author is trying to avoid.
The class UseDownloader is created and downloadSomething is called.
As the download progresses, the onProgress method is called. Since this is called from within the synchronized block, the Downloader motinor is locked. Inside our onProgress method, we need to lock our own resource, in this case lock. So when we are trying to synchronize on lock we are holding the Downloader monitor.
If another thread has decided that the download should be canceled, it will call setCanceled. This first tests done so it synchronized on the lock monitor and then calls removeListener. But removeListener requires the Downloader lock.
This kind of deadlock can be hard to find because it doesn't happen very often.
public static final int END_DOWNLOAD = 100;
class UseDownloader implements ProgressListener {
Downloader d;
Object lock = new Object();
boolean done = false;
public UseDownloader(Downloader d) {
this.d = d;
}
public void onProgress(int n) {
synchronized(lock) {
if (!done) {
// show some progress
}
}
}
public void downloadSomething() {
d.addListener(this);
d.start();
}
public boolean setCanceled() {
synchronized(lock) {
if (!done) {
done = true;
d.removeListener(this);
}
}
}
}
The following example leads to a deadlock because the MyProgressListener tries to acquire the Downloader lock while it's already acquired.
class MyProgressListener extends ProgressListener {
private Downloader myDownloader;
public MyProgressListener(Downloader downloader) {
myDownloader = downloader;
}
public void onProgress(int n) {
// starts and waits for a thread that accesses myDownloader
}
}
Downloader downloader = new Downloader(...);
downloader.addListener(new MyListener(downloader));
downloader.run();