Make two methods run one after another in thread while using synchronization - java

I have written a demo code for Atm machine while using synchronization
class Atm{
synchronized void checkBalance(String str){
System.out.print(str+" is checking his ");
try{Thread.sleep(1000);}catch(Exception e){
System.out.println(e);
}
System.out.println("Balance ");
}
synchronized void withdraw(String str, int amt){
System.out.print(str+ " is withdrawing amount: ");
try{Thread.sleep(1000);}catch(Exception e){
System.out.println(e);
}
System.out.println(amt);
}
}
class Customer extends Thread{
String name;
int amt;
Atm a;
Customer (Atm a){
this.a=a;
}
public void useAtm(){
a.checkBalance(name);
a.withdraw(name,amt);
}
public void run(){
useAtm();
}
}
after running the main method i get the output as Output where as soon as the thread 1 after releasing checkBalance, goes to withdraw method but thread 2 gets access to check balance before thread 1 could get monitor on withdraw and i get the output as such.
But on other cases i get the output as: Output 2 in order... where the threads access the methods one after another. How can i make sure that thread 2 or any other thread doesn't access checkBalance till thread 1 has completed accessing both checkBalance and withdraw?
Basically how to make the output as "Ram checks, Ram withdraws, S checks, S withdraws...." instead of "R checks, S checks, S withdraws, R withdraws"
Main:
public class Main {
public static void main(String[] args) {
// write your code here
Atm a=new Atm();
Customer c1=new Customer(a);
Customer c2=new Customer(a);
Customer c3=new Customer(a);
c1.name="Ram";
c1.amt=5000;
c2.name="Hari";
c2.amt=51000;
c3.name="Shyam";
c3.amt=545000;
Customer c4=new Customer(a);
Customer c5=new Customer(a);
Customer c6=new Customer(a);
c4.name="xam";
c4.amt=500220;
c5.name="pari";
c5.amt=5100220;
c6.name="ohyam";
c6.amt=54501200;
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
}
}

Here you did try to synchronize functions individually, which make sense if you want to use them separately synchronized. But when you want two functions to run in a synchronized way try using
public void useAtm(){
synchronized(a){
a.checkBalance(name);
a.withdraw(name,amt);
}
}
which will solve your problem. Try removing synchronized tag to methods.
void checkBalance(String str){
void withdraw(String str, int amt){
I hope it solved your issue.

Related

Best way to avoid deadlock for several objects transaction?

I was looking for deadlock example and stumbled across this code:
package com.example.thread.deadlock._synchronized;
public class BankAccount {
double balance;
int id;
BankAccount(int id, double balance) {
this.id = id;
this.balance = balance;
}
void withdraw(double amount) {
// Wait to simulate io like database access ...
try {Thread.sleep(10l);} catch (InterruptedException e) {}
balance -= amount;
}
void deposit(double amount) {
// Wait to simulate io like database access ...
try {Thread.sleep(10l);} catch (InterruptedException e) {}
balance += amount;
}
static void transfer(BankAccount from, BankAccount to, double amount) {
synchronized(from) {
from.withdraw(amount);
synchronized(to) {
to.deposit(amount);
}
}
}
public static void main(String[] args) {
final BankAccount fooAccount = new BankAccount(1, 100d);
final BankAccount barAccount = new BankAccount(2, 100d);
new Thread() {
public void run() {
BankAccount.transfer(fooAccount, barAccount, 10d);
}
}.start();
new Thread() {
public void run() {
BankAccount.transfer(barAccount, fooAccount, 10d);
}
}.start();
}
}
How would you change transfer method so that it doesn't cause deadlock? First thought is to create a shared lock for all accounts, but that of course would just kill all concurrency. So is there a good way to lock just two accounts involved into a transaction and not affect other accounts?
One way to avoid deadlocks in multi-lock situations is to always lock the objects in the same order.
In this case it would mean that you'd create a total ordering for all BankAccount objects. Luckily we've got an id that we can use, so you could always lock the lower id first and then (inside the other synchronized block) the higher id one.
This assumes that there's no BankAccount objects with identical ids, but that seems like a reasonable assumption.
Use two synchronized blocks separately instead of nested.
synchronized(from){
from.withdraw(amount);
}
synchronized(to){
to.deposit(amount);
}
So after from.withdraw(amount) is called, the lock on from is released before it tries to lock on to

can i make this class thread safe via immutable object?

i have a class in which i have 2 people which check balance and withdraw money from a common account .. i have made the the transaction thread safe via synchronized keyword but it has a lot of overhead , i have read about immutable objects and thread safety they provide . but i am unable to make this class thread safe via immutable object
code :
final class bank implements Runnable
{
private final int balance,min_balance;
bank(int bal,int mbal)
{
this.balance=bal;
this.min_balance=mbal;
}
#Override
public void run()
{
transaction();
}
public void transaction()
{
if(checkBalance()> min_balance)
{
System.out.println("checkin is done by : "+Thread.currentThread().getName()
+" and Balance left in the account is : "+checkBalance());
System.out.println(Thread.currentThread().getName()+" is going to sleep ...");
try{
Thread.currentThread().sleep(2000); }
catch(Exception e){
}
System.out.println(Thread.currentThread().getName()+" Woke up ..");
withdraw();
System.out.println(Thread.currentThread().getName()+" has made the withdrawl ..");
}
else{
lowBalance();
}
}
int checkBalance()
{
return balance;
}
void lowBalance()
{
System.out.println("balance is not adequate");
}
void withdraw()
{
balance=balance-20; //this wont work as balance is private
}
}
public class ryanmonica {
public static void main(String args[])
{
bank obj=new bank(100,20);
Thread t1=new Thread(obj);
Thread t2=new Thread(obj);
t1.setName("Ryan");
t2.setName("Monica");
t1.start();
t2.start();
}
}
An immutable object's state never changes. Since you need state change in your instance (balance and minBalance are changing), you need to use synchronization mechanism.
Immutable objects are thread-safe because they don't allow state change in their instances.

Java Threading - Solution to deadlock?

I have put together some Java code which demonstrates deadlock in threading. On it's own, I usually get 2 lines output and an exception, sometimes before and sometimes after the output lines which is expected. The exception I get is a NullPointerException on the first line of the transfer() method.
The problem I'm having is I'd like to know how to solve this deadlock problem. I have had a search on StackOverflow of this problem and found this page:
Avoid Deadlock example
As solutions, I have tried what Will Hartung and what Dreamcash posted but I still get exceptions when trying to use synchronize or a ReentrantLock object.
Here's the code:
Account class:
public class Account {
int id;
double balance;
public Account(int id, double balance){
this.id = id;
this.balance = balance;
}
public void withdraw(double amount){
balance = balance - amount;
}
public void deposit(double amount){
balance = balance + amount;
}
public int getID(){
return id;
}
public double getBalance(){
return balance;
}
}
Bank Class (a singleton):
public class Bank{
static Bank bank;
Account a1;
Account a2;
private Bank(){}
public static Bank getInstance(){
if(bank==null){
bank = new Bank();
bank.setAccountOne(new Account(1, 100));
bank.setAccountTwo(new Account(2, 100));
}
return bank;
}
public void transfer(Account from, Account to, double amount){
from.withdraw(amount);
to.deposit(amount);
}
public Account getAccountOne(){
return a1;
}
public Account getAccountTwo(){
return a2;
}
public void setAccountOne(Account acc){
a1 = acc;
}
public void setAccountTwo(Account acc){
a2 = acc;
}
}
PersonOne class:
public class PersonOne implements Runnable {
public void run() {
Bank bank = Bank.getInstance();
Account a1 = bank.getAccountOne();
Account a2 = bank.getAccountTwo();
bank.transfer(a2, a1, 10);
System.out.println("T1: New balance of A1 is " + a1.getBalance());
System.out.println("T1: New balance of A2 is " + a2.getBalance());
}
}
PersonTwo class:
public class PersonTwo implements Runnable {
public void run() {
Bank bank = Bank.getInstance();
Account a1 = bank.getAccountOne();
Account a2 = bank.getAccountTwo();
bank.transfer(a1, a2, 10);
System.out.println("T2: New balance of A1 is " + a1.getBalance());
System.out.println("T2: New balance of A2 is " + a2.getBalance());
}
}
And finally, my main method
public static void main(String[] args){
PersonOne p1 = new PersonOne();
PersonTwo p2 = new PersonTwo();
Thread t1 = new Thread(p1);
Thread t2 = new Thread(p2);
t1.start();
t2.start();
}
The exception I get is a NullPointerException on the first line of the transfer() method.
The problem I'm having is I'd like to know how to solve this deadlock problem.
Your code cannot possible provoke any deadlocks. What it does provoke is write visibility issues: one of the threads gets to invoke the lazy Bank initializer and the other thread does not see the write.
To get deadlocks you first need any kind of locking (the synchronized keyword). Your particular NPE problem will be solved by adding synchronized to the getInstance method and it will not introduce any deadlocks.
My conclusion is that your best recourse is reading some introductory material on concurrency in Java.
There is a number of solutions and some of the less obvious ones are
use one thread and don't use locks. In this example, the code will me much simpler and much faster with just one thread as the overhead of locks exceeds the work being done.
as this is just an example, you cold use just one global lock. This will not perform as well as multiple locks but it is much simpler and if you don't need the performance you should do the simpler , less likely to get bugs. This cannot get a deadlock.
if you have to use multiple lock because this is homework, you can ensure you always lock in the same order. You can do this by sorting the objects on a unique key and always lock the "first" item first.
lastly, you can lock the objects in any order by use tryLock on the second account. If this fails, release both locks and try again. You can perform a tryLock on a monitor using Unsafe.tryMonitor().
Thanks for your answers.
I'm currently learning about threading. In the above, I was purposefully trying to create a deadlock, so that I could learn how to solve the problem of deadlocks (if I actually wanted a program that did the above, I would just avoid multi-threading).
The reason I used a singleton was so the two threads would be trying to use the same objects.
So... the above was the code I used to try to recreate a deadlock, so I was expecting problems/exceptions when running. One way I tried to then fix it was by rewriting the transfer method to look like this:
public void transfer(Account from, Account to, double amount){
synchronized(from){
synchronized(to){
from.withdraw(amount);
to.withdraw(amount);
}
}
}
But I'd get a NullPointerException on the synchronized(from) line.
I also tried this in the transfer method (and account had a ReentrantLock object inside it). But this time I'd get a NullPointerException on the line that reads from.getLock().unlock()
public void transfer(Account from, Account to, double amount){
while(true){
try{
if(from.getLock().tryLock()){
try{
if(to.getLock().tryLock()){
from.withdraw(amount);
to.withdraw(amount);
break;
}
} finally {
to.getLock().unlock();
}
}
} finally{
from.getLock().unlock();
}
Random random = new Random();
int i = random.nextInt(1000);
try {
Thread.sleep(1000 + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Thread starts running and terminates itself

Update : Thanks everyone! I've modified the program as per the suggestions and the code given below is the modified code.
Original Post :
I've gone through some "Apply and Analyze" type of questions and in one question, the programmer has been asked to apply multithreading concept for three reservation counters of a cinema theater and calculate the total booking numbers and amount collected in a show.
And I've written a program for the same which you can see below:
import java.io.*;
import java.lang.*;
class Cinema
{
int no=0,price=0;
synchronized void reservation(int n,int p)
{
no=no+n;
price=price+p;
}
}
class Counter implements Runnable
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Cinema c;
int not,cost;
Counter(Cinema c)
{
this.c=c;
}
public void run()
{
try
{
System.out.print("\nCounter 1");
System.out.print("\nEnter the no. of tickets :");
not=Integer.parseInt(br.readLine());
cost=not*150;
c.reservation(not,cost);
}
catch(IOException e){System.out.print("\n"+e);}
}
}
class CinemaMain
{
public static void main(String args[])throws IOException
{
Cinema c=new Cinema();
System.out.print("\nCounter 1");
Thread c1=new Thread(new Counter(c));
c1.start();
c1.join();
System.out.print("\nCounter 2");
Thread c2=new Thread(new Counter(c));
c2.start();
c2.join();
System.out.print("\nCounter 3");
Thread c3=new Thread(new Counter(c));
c3.start();
c3.join();
try
{
Thread.sleep(500);
}
catch(InterruptedException ie)
{
System.out.print("\n"+ie);
}
System.out.print("\nTotal no. of tickets :"+c.no);
System.out.print("\nTotal Money collected:"+c.price);
}
}
I can compile it just fine, but when I run the program, this is what I get -->LINK (since I don't have 10 reputation, I couldn't post the image here, sorry!) I don't know why, it doesn't ask for input even though I've written the code to get input in the run method.
I can compile it just fine, but when I run the program, this is what I get ...
There are a couple of things wrong with your program:
The main thread is not waiting for the Counter threads to finish before it prints out the totals. If you need to wait for a thread to complete then you call thread.join() on it.
Thread counter1 = new Thread(new Counter1(c));
counter1.start();
// start other threads here...
// now wait for the counter1 to finish
counter1.join();
In your case, the 3 Counters are forked but the main only sleeps a bit and then quits. The Counter threads are still running.
Each of the Counter threads is adding values to fields inside the Cinema but there is no synchronization in Cinema. Anytime two threads are modifying the same field, there must be some mutex protection and memory synchronization.
The easy thing to do here is to make the Cinema.reservation(...) method be synchronized. Then each of the Counter objects will get a lock on the Cinema instance which will ensure only one Counter updates the Cinema at one time. The synchronized keyword also ensures that the fields in the Cinema object are memory synchronized as well.
synchronized void reservation(int n,int p) { ...
As always, you should consider using the ExecutorService classes instead of forking threads yourself. See the Java tutorial.
Try this Approach ;
import java.io.*;
import java.lang.*;
public class Cinema
{
int no=0,price=0;
synchronized void reservation(int n,int p)
{
no=no+n;
price=price+p;
}
public static void main(String args[])throws IOException, InterruptedException
{
Cinema c=new Cinema();
Thread t1 = new Thread(new Counter(c,"Counter 1"));
t1.start();
Thread t2 = new Thread(new Counter(c,"Counter 2"));
t2.start();
Thread t3 = new Thread(new Counter(c,"Counter 3"));
t3.start();
t1.join();
t2.join();
t3.join();
try
{
Thread.sleep(100);
}
catch(InterruptedException ie)
{
System.out.print("\n"+ie);
}
System.out.print("\nTotal no. of tickets :"+c.no);
System.out.print("\nTotal Money collected:"+c.price);
}
}
class Counter implements Runnable
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
Cinema c;
int not,cost;
String counterName;
Counter(Cinema c,String counterName)
{
this.c=c;
this.counterName=counterName;
}
public void run()
{
try
{
synchronized(c) {
System.out.print("\n" + counterName);
System.out.print("\nEnter the no. of tickets :");
not=Integer.parseInt(br.readLine());
cost=not*150;
c.reservation(not,cost);
}
}
catch(IOException e){System.out.print("\n"+e);}
}
}
I have made a single Counter class instead of 3 classes you are using.
I made the reservation method to be synchronized.
I called join method on all the three threads. So the program will not terminate abruptly.TGhe last thread that would teminate would be main.
In run() method , I locked the Cinema object c. This will resolve your issue of Buffered Reader at this moment of time. But in real world scenario different threads will be run by different people. So no need to lock the Cinema object there.it is just for your usage.
Why do you need to make threads when you can just make it way simpler?
import java.io.*;
import java.lang.*;
import java.util.Scanner;
public class Cinema {
public Cinema(){
int no=0,price=0;
}
public int Count () {
int not,not2, not3, cost,cost2,cost3;
System.out.print("\nCounter 1");
System.out.print("\nEnter the no. of tickets: ");
Scanner br=new Scanner(System.in);
String input=br.nextLine();
not=Integer.parseInt(input);
cost=not*150;
System.out.println("Cost of tickets: "+cost);
System.out.print("\nCounter 2");
System.out.print("\nEnter the no. of tickets: ");
Scanner br2=new Scanner(System.in);
String input2=br2.nextLine();
not2=Integer.parseInt(input2);
cost2=not2*150;
System.out.println("Cost of tickets: "+cost2);
System.out.print("\nCounter 3");
System.out.print("\nEnter the no. of tickets: ");
Scanner br3=new Scanner(System.in);
String input3=br3.nextLine();
not3=Integer.parseInt(input3);
cost3=not3*150;
System.out.println("Cost of tickets: "+cost3);
int total=cost+cost2+cost3;
int tickets=not+not2+not3;
System.out.println("Total price for tickets is: "+total);
System.out.println("Total number of tickets is: "+tickets);
return total;
}
public static void main(String args[])
{
Cinema c=new Cinema();
c.Count();
}
}

why is synchronised method not working?

i was working with the synchronized statement and made the following program...synchronized the runn class with this as object reference ..bt smhw the desired output is nt there....
class runn extends Thread {
String s;
runn(String a) {
s=a;
start();
}
public void show() {
System.out.print("["+s);
try {
sleep(50);
} catch(Exception a){}
System.out.print("]");
}
public void run() {
synchronized(this) {
show();
}
}
}
public class multi4 {
public static void main(String[] args) throws InterruptedException{
new runn("hello ");
new runn("this is ");
new runn("multithreading");
}
}
The output should be :
[hello][this is][multithreading]
but synchronisation is not working smhw
Please help.
Two mistakes:
You synchronized on the individual runn objects. This has no effect because each thread uses a different synchronization object.
The synchronized keyword does not magically cause threads to run in order. It merely prevents threads from attempting to execute the synchronized block at the same time, if you synchronize on the same object. They may still run in any order, but wouldn't be able to interleave their output. That is, if you synchronized on a shared object, you could get e.g. [this is][hello][multithreading], but not [this is[hello][multithreading]].

Categories