AOP concurrency

          

AOP concurrency

 

Spring 2.5 Aspect Oriented Programming, AOP

Chapter 5
Design with AOP

This chapter excerpt from Spring 2.5 Aspect Oriented Programming by Massimiliano Dessì, is printed with permission from Packt Publishing, Copyright 2007.

NEXT>>

AOP concurrency

For many developers, concurrency remains a mystery.

Concurrency is the system's ability to act with several requests simultaneously, such a way that threads don't corrupt the state of objects when they gain access at the same time.

A number of good books have been written on this subject, such as Concurrent Programming in Java and Java Concurrency in Practice. They deserve much attention, since concurrency is an aspect that's hard to understand, and not immediately visible to developers. Problems in the area of concurrency are hard to reproduce. However, it's important to keep concurrency in mind to assure that the application is robust regardless of the number of users it will serve.

If we don't take into account concurrency and document when and how the problems of concurrency are considered, we will build an application taking some risks by supposing that the CPU will never simultaneously schedule processes on parts of our application that are not thread-safe.

To ensure the building of robust and scalable systems, we use proper patterns. There are JDK packages just for concurrency. They are in the java.util.concurrent package, a result of JSR-166.

One of these patterns is the read-write lock pattern, which consists of is the interface java.util.concurrent.locks.ReadWriteLock and some implementations, one of which is ReentrantReadWriteLock.

The goal of ReadWriteLock is to allow the reading of an object from a virtually endless number of threads, while only one thread at a time can modify it. In this way, the state of the object can never be corrupted because threads reading the object's state will always read up-to-date data, and the thread modifying the state of the object in question will be able to act without the possibility of the object's state being corrupted. Another necessary feature is that the result of a thread's action can be visible to the other threads. The behavior is the same as we could have achieved using synchronized, but when using a read-write lock we are explicitly synchronizing the actions, whereas with synchronized synchronization is implicit.

Now let's see an example of ReadWriteLock on the BankAccountThreadSafe object.

Before the read operation that needs to be safe, we set the read lock. After the read operation, we release the read lock.

Before the write operation that needs to be safe, we set the write lock. After a state modifi cation, we release the write lock.

package org.springaop.chapter.five.concurrent;

import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public final class BankAccountThreadSafe {
        public BankAccountThreadSafe(Integer id) {
                   this.id = id;
                   balance = new Float(0);
                   startDate = new Date();
        }
        public BankAccountThreadSafe(Integer id, Float balance) {
                   this.id = id;
                    this.balance = balance;
                    startDate = new Date();
        }
         public BankAccountThreadSafe(Integer id, Float balance, Date start)
         {
                     this.id = id;
                     this.balance = balance;
                     this.startDate = start;
          }
          public boolean debitOperation(Float debit) {
                     wLock.lock();
                     try {
                               float balance = getBalance();
                             if (balance < debit) {
                                     return false;
                          } else {
                                     setBalance(balance - debit);
                                            return true;
                              }
                         } finally {
                                   wLock.unlock();
                            }
                         }

            public void creditOperation(Float credit) {
                    wLock.lock(); 
                    try {
                         setBalance(getBalance() + credit);
                        } finally {
                               wLock.unlock();
                           }
                         }
            private void setBalance(Float balance) {
                 wLock.lock();
                 try {
                       balance = balance;
                       } finally {
                               wLock.unlock();
                            }
                       }
            public Float getBalance() {
                 rLock.lock();
                 try {
                      return balance;
                     } finally {
                           rLock.unlock();
                     }
             }
             public Integer getId() {
                    return id;
             }
             public Date getStartDate() {
                    return (Date) startDate.clone();
              }
     private Float balance;
     private final Integer id;
     private final Date startDate;
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
     private final Lock rLock = lock.readLock();
     private final Lock wLock = lock.writeLock();
}

BankAccountThreadSafe is a class that doesn't allow a bank account to be overdrawn (that is, have a negative balance), and it's an example of a thread-safe class. The final fi elds are set in the constructors, hence implicitly thread-safe. The balance fi eld, on the other hand, is managed in a thread-safe way by the setBalance, getBalance, creditOperation, and debitOperation methods.

In other words, this class is correctly programmed, concurrency-wise. The problem is that wherever we would like to have those characteristics, we have to write the same code (especially the finally block containing the lock's release).

We can solve that by writing an aspect that carries out that task for us.

  • A state modifi cation is execution(void com.mycompany.BankAccount.set*(*))
  • A safe read is execution(* com.mycompany.BankAccount.getBalance())

    package org.springaop.chapter.five.concurrent;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    @Aspect
    public class BankAccountAspect {
             /*pointcuts*/
            @Pointcut(
    "execution(* org.springaop.chapter.five.concurrent.BankAccount.
    getBalance())")
    public void safeRead(){}
    @Pointcut(
           "execution(* org.springaop.chapter.five.concurrent.BankAccount.
    set*(*))")
          public void stateModification(){}
          @Pointcut(
    "execution(* org.springaop.chapter.five.concurrent.BankAccount. getId())")
           public void getId(){}
    @Pointcut("execution(* org.springaop.chapter.five.concurrent.
    BankAccount.getStartDate()))
          public void getStartDate(){}
              /*advices*/
    @Before("safeRead()")
    public void beforeSafeRead() {
            rLock.lock();
    }
    @After("safeRead()")
    public void afterSafeRead() {
           rLock.unlock();
    }
    @Before("stateModification()")
    public void beforeSafeWrite() {
           wLock.lock();
    }
    @After("stateModification()")
    public void afterSafeWrite() {
            wLock.unlock();
    }
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock rLock = lock.readLock();
    private final Lock wLock = lock.writeLock();
    }

The BankAccountAspect class applies the crosscutting functionality. In this case, the functionality is calling the lock and unlock methods on the ReadLock and the WriteLock. The before methods apply the locks with the @Before annotation, while the after methods release the locks as if they were in the fi nal block, with the @After annotation that is always executed (an after-fi nally advice).

In this way the BankAccount class can become much easier, clearer, and briefer. It doesn't need any indication that it can be executed in a thread-safe manner.

package org.springaop.chapter.five.concurrent;
import java.util.Date;
public class BankAccount {
     public BankAccount(Integer id) {
          this.id = id;
          this.balance = new Float(0);
          this.startDate = new Date();
     }
     public BankAccount(Integer id, Float balance) {
          this.id = id;
          this.balance = balance;
          this.startDate = new Date();
     }
public BankAccount(Integer id, Float balance, Date start) {
         this.id = id;
         this.balance = balance;
         this.startDate = start;
}
public boolean debitOperation(Float debit) {
float balance = getBalance();
if (balance < debit) {
      return false;
} else {
       setBalance(balance - debit);
       return true;
}
}
public void creditOperation(Float credit) {
      setBalance(getBalance() + credit);
}
private void setBalance(Float balance) {
     this.balance = balance;
}
public Float getBalance() {
    return balance;
}
public Integer getId() {
    return id;
}
public Date getStartDate() {
    return (Date) startDate.clone();
}
private Float balance;
private final Integer id;
private final Date startDate;
}

Another good design choice, together with the use of ReadWriteLock when necessary, is using objects that once built are immutable, and therefore, not corruptible and can be easily shared between threads.

NEXT>>

Also read

Aspect-Oriented Programming

Explain the concepts and capabilities of Aspect-Oriented Programming, AOP.
What is Aspect in AOP?
AOP approach addresses Crosscutting concerns. Explain
The components of AOP are advices/interceptors, introductions, metadata, and pointcuts. Explain them
AOP vs OOPs...........

OOPS in .NET

What is the relation between Classes and Objects? Explain different properties of Object Oriented Systems. What is difference between Association, Aggregation and Inheritance relationships? Explain the features of an abstract class in NET. Difference between abstract classes and interfaces Similarities and difference between Class and structure in .NET Features of Static/Shared classes. What is Operator Overloading in .NET?.............

What is object oriented programming (OOP)?

The object oriented programming is commonly known as OOP. Most of the languages are developed using OOP concept. Object-oriented programming (OOP) is a programming concept that uses "objects" to develop a system.........

What are the various elements of OOP?

Various elements of OOP are.........

Explain an object, class and Method.

An object is an entity that keeps together state and behaviors. For instance, a car encapsulates state such as red color, 900 cc etc and behaviors as 'Start', 'Stop' etc., so does an object...............



Write your comment - Share Knowledge and Experience


 

 
Latest placement tests
Latest links
 
Latest MCQs
» General awareness - Banking » ASP.NET » PL/SQL » Mechanical Engineering
» IAS Prelims GS » Java » Programming Language » Electrical Engineering
» English » C++ » Software Engineering » Electronic Engineering
» Quantitative Aptitude » Oracle » English » Finance
Home | About us | Sitemap | Contact us | We are hiring