fortm
fortm

Reputation: 4198

Locking on static object

There are multiple instance of Class A that runs at a time.

Class A calls multiple instances of Class B in its run.

public Class Main {

    public static void main(String args[] ) {

        A a1 = new A();
        Thread t1 = new Thread(a1);
        t1.start();

        A a2 = new A();
        Thread t2 = new Thread(a2);
        t2.start();
    }
}

Class A implements Runnable {

    public void run() {

        B b1 = new B();
        Thread t11 = new Thread(b1);
        t11.start();

        B b2 = new B();
        Thread t21 = new Thread(b2);
        t21.start();
    }
}

There is method named "method" in class B where a Set Collection is edited. That edit is done based on static lock in Class B.

EDIT-

Class B implements Runnable {

    private final static Object LOCK = new Object();
    private final static Set<T> busyRecords = new HashSet<T>();

    public void waitToWorkOn(final T obj) {
        synchronized(LOCK) {
            while (busyRecords.contains(obj)) {
        LOCK.wait(); //go to sleep
       }
       busyRecords.add(obj);            
    }
    }

    public void doneWith(final T obj) {
        synchronized(LOCK) {
           busyRecords.remove(obj);
      LOCK.notifyAll(); 
    }
    }

    public void mathod(obj)  {

     try{
        waitToWorkOn(obj);

         .. do some work with obj
     }
     finally {
        doneWith(obj);
     }
    }

    public void run() {
        method(getObj())
    }
}

But that Set does not need concurrency control when it is accessed from different "A" instances. Only within an A instance, it needs to be locked for all B instances.

By this I mean, that when 2 instances of A are running, they should not be made to wait. But within an A instance if 2 B objects pick same obj, they have to wait inside LOCK.wait.

I don't think that LOCK can be made non-static as A calls multiple instances of B.Can we tune LOCK object here for better concurrency across A objects.

Upvotes: 0

Views: 136

Answers (1)

jtahlborn
jtahlborn

Reputation: 53694

You can create a thread-safe instance of the shared collection and pass it to all the Bs for a given A.

Class A implements Runnable {

    public void run() {

        // create shared set instance scoped to A, and make it thread-safe
        Set col = Collections.synchronizedSet(new HashSet());

        B b1 = new B(col);
        Thread t11 = new Thread(b1);
        t11.start();

        B b2 = new B(col);
        Thread t21 = new Thread(b2);
        t21.start();
    }
}

Class B implements Runnable {

    private final Set<T> someSet;

    private B(Set<T> someSet) {
      this.someSet = someSet;
    }

    public void method(final T obj) {
        someSet.add(obj);
    }

    public void run() {
        method()
    }
}

Upvotes: 1

Related Questions