Java: 基于对象值同步

Java: Synchronization based on object value

我想根据输入参数同步一个方法或一个块。

所以我有一个 API,它在 post 有效负载中有两个 long 类型(可以是原始类型或包装器)的输入(比如 id1 和 id2),可以是 JSON.这个API会被多个线程随机同时或不同时间调用

现在如果第一个 API 调用有 id1=1 和 id2=1,同时另一个 API 调用有 id1=1 和 id2=1,它应该等待第一个 API 调用在执行第二个调用之前完成处理。如果第二个 API 调用具有不同的值组合,如 id1=1 和 id2=2,它应该并行进行,没有任何等待时间。

我不介意创建 API 资源方法也可以调用的服务方法,而不是直接在 API 资源方法中处理。

我正在使用 Spring boot Rest Controlller APIs.

**编辑** 我已经尝试按照建议使用地图,但这部分有效。它等待所有输入值,而不仅仅是相同的输入值。下面是我的代码:
public static void main(String[] args) throws Exception {
    ApplicationContext context = SpringApplication.run(Application.class, args);
    AccountResource ar = context.getBean(AccountResource.class);
    UID uid1 = new UID();
    uid1.setFieldId(1);
    uid1.setLetterFieldId(1);
    UID uid2 = new UID();
    uid2.setFieldId(2);
    uid2.setLetterFieldId(2);
    UID uid3 = new UID();
    uid3.setFieldId(1);
    uid3.setLetterFieldId(1);
    Runnable r1 = new Runnable() {

        @Override
        public void run() {
            while (true) {
                ar.test(uid1);
            }

        }
    };
    Runnable r2 = new Runnable() {

        @Override
        public void run() {
            while (true) {
                ar.test(uid2);
            }

        }
    };
    Runnable r3 = new Runnable() {

        @Override
        public void run() {
            while (true) {
                ar.test(uid3);
            }

        }
    };
    Thread t1 = new Thread(r1);
    t1.start();
    Thread t2 = new Thread(r2);
    t2.start();
    Thread t3 = new Thread(r3);
    t3.start();

}
@Path("v1/account")
@Service
public class AccountResource {
public void test(UID uid) {
        uidFieldValidator.setUid(uid);
        Object lock;
        synchronized (map) {
            lock = map.get(uid);
            if (lock == null) {
                map.put(uid, (lock = new Object()));
            }
            synchronized (lock) {
                //some operation
            }
        }
    }
}

package com.urman.hibernate.test;

import java.util.Objects;

public class UID {
    
    private long letterFieldId;
    private long fieldId;
    private String value;
    public long getLetterFieldId() {
        return letterFieldId;
    }
    public void setLetterFieldId(long letterFieldId) {
        this.letterFieldId = letterFieldId;
    }
    public long getFieldId() {
        return fieldId;
    }
    public void setFieldId(long fieldId) {
        this.fieldId = fieldId;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    @Override
    public int hashCode() {
        return Objects.hash(fieldId, letterFieldId);
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        UID other = (UID) obj;
        return fieldId == other.fieldId && letterFieldId == other.letterFieldId;
    }
}

您需要一组锁,您可以将其保存在地图中并根据需要进行分配。这里我假设你的 id1 和 id2 是字符串;酌情调整。

 Map<String,Object> lockMap = new HashMap<>();
   :

 void someMethod(String id1, String id2) {
     Object lock;
     synchronized (lockMap) {
         lock = lockMap.get(id1+id2);
         if (lock == null) lockMap.put(id1+id2, (lock = new Object()));
     }
     synchronized (lock) {
         :
     }
 }

地图操作需要一点点 'global' 同步,或者您可以使用其中一种并发实现。为了简化实现,我使用了基础 HashMap。

选择锁后,对其进行同步。