Reputation: 1253
I was studying MultiThreading
concepts. I came across ReentrantLock
. It has methods lock
and trylock
. As I studied them further, I understood that they can be used instead of synchronized
keyword block or method. So I tried them again with classic example of AccountDanger
given in Kathie Sierra book. I observed that lock
method DO allow turn taking with other threads. But trylock
boolean method NOT allow turn taking with other threads. example below:
with lock
method
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
lock.lock();
try{
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}finally{
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
above code with lock
method allowing both Mark
and Phew
threads to take turns.
with trylock
method
package p1;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AccountDanger implements Runnable {
private Account account = new Account();
private int amt = 10;
Lock lock = new ReentrantLock();
Object obj = new Object();
public void run(){
for(int i=0;i<10;i++){
try{
if(lock.tryLock()){
if(account.getBalance()>=amt){
System.out.println(Thread.currentThread().getName()+" is going to withdraw..");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.withdraw(amt);
System.out.println(Thread.currentThread().getName()+" has withdrawn. Balance left is : "+account.getBalance());
}
else{
System.out.println("not enough balance for "+Thread.currentThread().getName());
}
}
}
finally {
if(lock.tryLock()){
lock.unlock();
}
}
if(account.getBalance()<0){
System.out.println("account is over withdrawn!!!");
}
}
}
public static void main(String[] args) throws InterruptedException{
AccountDanger ad = new AccountDanger();
Thread t1 = new Thread(ad,"Mark");
Thread t2 = new Thread(ad,"Phew");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("final balance left is : "+ad.account.getBalance());
}
}
above code does NOT allowing Phew
thread to take turns even when Thread.sleep()
method is called.
Account class
package p1;
public class Account{
private int balance = 100;
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
public void withdraw(int amount){
this.balance = this.balance - amount;
}
}
although both methods are, no doubt, preventing balance to get negative. But I don't understand that why is trylock
being so serious about the process that it does not allow other thread to come in between the execution even when Thread.sleep
is called within. Even if I use lock.unlock
statement in finally
block after catch block of Thread.sleep
, then also only mark
thread is executing.
Upvotes: 0
Views: 1024
Reputation: 14999
Your basic misunderstanding was that trylock
did not aquire a lock, which it does; as I stated in my comment, trylock
is equivalent to lock
except it doesn't block if the lock cannot be obtained.
What's happening in your case is this:
run
method and terminated the Phew thread.Upvotes: 1