Reputation: 161
I have three objects: A, B, and C. I need such synchronization so that blocks synchronized with objects A and B can be executed in parallel, and when block synchronized with objects A or block synchronized with objects B is executed, block synchronized with objects C cannot be executed. And when block synchronized with objects C is executed, blocks synchronized with objects A and B cannot be executed. I tried to use object C as list, and objects A and B as objects stored in this list, but it did not work. Please tell me, is it possible to somehow configure such synchronization?
import java.util.ArrayList;
import java.util.List;
public class Threads {
public List<Res> lst = new ArrayList();
public void startThreads(){
lst.add(new Res());
lst.add(new Res());
Thread t1 = new Thread(new work1());
Thread t2 = new Thread(new work2());
Thread t3 = new Thread(new work3());
t1.start();
t2.start();
t3.start();
}
public class work1 implements Runnable {
@Override
public void run() {
Method1();
}
}
public class work2 implements Runnable {
@Override
public void run() {
Method2();
}
}
public class work3 implements Runnable {
@Override
public void run() {
Method3();
}
}
public void Method1(){
synchronized (lst.get(0)/*obj A*/){
//some work
}
}
public void Method2(){
synchronized (lst.get(1)/*obj B*/){
//some work
}
}
public void Method3(){
synchronized (lst)/*obj C*/{
//some work
}
}
}
Class Res:
public class Res {
public int number = 0;
}
Class Main:
public class Main {
public static void main(String[] args) throws InterruptedException {
Threads t = new Threads();
t.startThreads();
}
}
Upvotes: 0
Views: 87
Reputation: 10653
In your case simplest (Not recommended) solution is to guard Block A and Block B with different monitor objects and guard Block C with the monitor obects of both A and B.
public void Method1(){
synchronized (A){
//some work
}
}
public void Method2(){
synchronized (B){
//some work
}
}
public void Method3(){
synchronized (A){
synchronized (B){
//some work
}
}
}
Same can be done using Locks as well.
public void Method1(){
lockA.lock();
try{
//some work
} finally {
lockA.unlock();
}
}
public void Method2(){
lockB.lock();
try{
//some work
} finally {
lockB.unlock();
}
}
public void Method3(){
lockA.lock();
try{
lockB.lock();
try{
//some work
} finally {
lockB.unlock();
}
} finally {
lockA.unlock();
}
}
Or you can use read/write lock as suggested by shmosel in the comments.
public void Method1(){
readWriteLock.readLock().lock();
try{
//some work
} finally {
readWriteLock.readLock().unlock();
}
}
public void Method2(){
readWriteLock.readLock().lock();
try{
//some work
} finally {
readWriteLock.readLock().unlock();
}
}
public void Method3(){
readWriteLock.writeLock().lock();
try{
//some work
} finally {
readWriteLock.writeLock().unlock();
}
}
You can also use CountDownLatch for the same purpose, though read/write lock is the easiest one.
Upvotes: 1