this is for my NXT brick.
Let's say I have two DIFFERENT classes, Class A
and Class B
, and each class has its OWN thread running.
However, there is a static variable instance called MotorA
that is shared by both classes. This MotorA
variable is a PHYSICAL motor whose motion can be controlled by the two classes. Both Class A
and Class B
's threads can control MotorA
's motion but I only want ONE of them to control MotorA
at a time.
For example, if Class A
is trying to rotate MotorA
forward and Class B
is trying to rotate MotorA
backward, I only want Class A
to rotate MotorA
forward and block Class B's effect.
Question: Can I use the SAME lock to synchronize methods in threads from DIFFERENT classes?
Yes, you can. You can actually do it like this:
class MotorA {
private static MotorA motor = new MotorA();
private static final java.util.concurrent.locks.Lock lock = new java.util.concurrent.locks.ReentrantLock();
private MotorA() { }
public static MotorA getMotorA() {
return motor;
}
public static Lock getLock() {
return lock;
}
/* here go business methods for MotorA */
}
Next, when you want to do any operation on MotorA instance, you just need:
getLock()
getMotorA()
MotorA
instace In this case, the access to the resource will be safe from multiple threads.
Or you can simply synchronize on the instance of MotorA:
class UserOfMotor1 {
public void doOperationInMotor1Thread() {
synchronized(MotorA.getMotorA()) {
MotorA motor = MotorA.getMotorA();
motor.soSth();
}
}
}
But in this case, you will also have to use synchronized()
block in whenever thread uses the shared resource - in your case MotorA
. If you use this method of controlling synchronization, you must ensure that you are synchronizing on the same object in different threads - in this case MotorA
is a Singleton
so you always get the same instance.
Each thread can synchronize
on the motor instance while its working with it. However, if one thread is going to be using multiple motors together, this would lead you to acquire locks on each motor. Then you'd have to be very careful about the order you nest your synchronized blocks, or you will have intermittent deadlocks.
Instead, I suggest that you use a single lock for all motors, and never use any motor without holding that lock. Since the motors are static resources, this lock could be too. In a big program, it would be a bit safer to create your own private lock, and carefully control who can access it. In this context, it's probably okay to have a global lock variable that any code can access.
final class Locks {
public static final Object MOTORS = new Object();
private Locks() { /* Disallow instantiation. */ }
}
To use it:
final class ThreadA extends Thread {
public void run() {
...
synchronized(Locks.MOTORS) {
Motor motorA = Motors.A;
motorA.setSpeed(...);
...
}
}
}
You wouldn't need to limit yourself to just motors; the key is not to have nested blocks synchronizing on different objects. That might happen directly in one method, or because you call one method with a synchronized block from a synchronized block in another method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With