如何根据调用它的对象实例来序列化函数,如果同一实例在线程中调用,则进行序列化,否则不序列化

发布于 2024-12-04 23:59:36 字数 141 浏览 1 评论 0原文

我有一个存款功能,多个客户同时调用。我希望存款函数在同一客户端(例如 id=someUniqueNo 的客户端)再次调用它时同步,但在其他客户端调用它时不同步?我怎样才能做到这一点。 在项目中使用Spring框架,即使任何带有该框架的解决方案提供了这种模式,它也很酷。

I have a deposit function which is called by multiple clients at same time. I want the deposit function synchronized when same client (say client with id=someUniqueNo) calls it again but not synchronized when other client else call it ? How can I achieve this.
Using Spring framework in the project , Its cool even if any solution with the framework provides for such pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

比忠 2024-12-11 23:59:36

像这样的东西会起作用吗?

private Map<String, ReentrantLock> lockMap = new HashMap<String, ReentrantLock>();

public void deposit(String clientId) {
    updateLockMap(clientId);

    ReentrantLock lock = lockMap.get(clientId);
    try {
        if(lock.tryLock(1, TimeUnit.MINUTES)) {
            // do deposit stuff
        }
    } catch (InterruptedException e) {
        // log
    } finally {
        lock.unlock();
    }
}

private void updateLockMap(String clientId) {
    if(!lockMap.keySet().contains(clientId)) {
        lockMap.put(clientId, new ReentrantLock());
    }
}

Would something like this work?

private Map<String, ReentrantLock> lockMap = new HashMap<String, ReentrantLock>();

public void deposit(String clientId) {
    updateLockMap(clientId);

    ReentrantLock lock = lockMap.get(clientId);
    try {
        if(lock.tryLock(1, TimeUnit.MINUTES)) {
            // do deposit stuff
        }
    } catch (InterruptedException e) {
        // log
    } finally {
        lock.unlock();
    }
}

private void updateLockMap(String clientId) {
    if(!lockMap.keySet().contains(clientId)) {
        lockMap.put(clientId, new ReentrantLock());
    }
}
傲性难收 2024-12-11 23:59:36
public void deposit(String clientId){
   String id = clientId;
   while(id.equals("someClientID")){
         synchronized(lockObject){
             // Do your stuff here in a sync'd way
          }
   }
   else
   {
     // Do your stuff here in a NON synch'd way 
   }

 }

第二次尝试:(未测试!)

public void deposit(String clientId){
    String id = clientId;
   // callers is a ConcurrenthashMap<String,String>
     while(callers.get(id) != null){  
     synchronized(callers.get(id)){  // client already in call, so wait
        wait(); 
     }
   }       
      callers.put(id,id);  // client is ready to run a new call, so setup 
      // Do your stuff here in a NON synch'd way 
 synchronized(callers.get(id)){  // client done with a call , 
                      //so notify others who are calling
    callers.put(id,null);
    notifyAll();
       }
}  

第三次尝试(已测试且工作正常)

    public class SyncTest {
     static int[] balances = new int[]{ 1,10,100,1000,10000};
public static void main(String[] args) {
    // TODO Auto-generated method stub
    SyncTest test = new SyncTest();
    Client c1 = new Client("0", test,1);
    Client c2 = new Client("1", test,10);
    Client c3 = new Client("2", test,100);
    Client c4 = new Client("3", test,1000);
    Client c5 = new Client("4", test,10000);

    Thread[] threads = new Thread[5];
    threads[0] = new Thread(c1);
    threads[1] = new Thread(c2);
    threads[2] = new Thread(c3);
    threads[3] = new Thread(c4);
    threads[4] = new Thread(c5);

    for(int i=0;i<5;i++){
        threads[i].start();
    }
    for(int i=0;i<5;i++){
        try{
            threads[i].join();
        }
        catch(InterruptedException ex){
        }
    }


    System.out.println("Final balances are ");
    for(int i=0;i<5;i++){
        System.out.print(balances[i] + " , " );
    }
}

ConcurrentHashMap<String,String> callers = new ConcurrentHashMap<String, String>();

public void deposit(Client c) throws InterruptedException{
    String id = c.id;
    int amount = c.amount;
    if(id == null) return ;

   // callers is a ConcurrenthashMap<String,String>
    System.out.println("Client " + id + " in deposit. Checking if already running..");
    while( callers.get(id) != null && !(callers.get(id).equals("X"))) {
       synchronized(id){
        System.out.println("Client " + id + " in deposit. Found already running,going to wait..");
        id.wait(); 
     }
   }
    if(callers == null){
        throw new NullPointerException("Callers is null!!");
    }

    System.out.println("Client " + id + " in deposit. Found not running already,  Now running..");
    callers.put(id,id);
    int index = Integer.parseInt(id);
    balances[index] += amount;
    Thread.sleep(2000);
    synchronized(id){
        String old = callers.put(id,"X");
        id.notifyAll();
       System.out.println("Client " + id + " in deposit. Finished running ,  Notifying..");
    }
}

static class Client implements Runnable {
    String id ;
    SyncTest test;
    int amount;
    Client c = this;

    Client(String id , SyncTest t, int am){
        this.id = id;
        test = t;
        amount = am;
    }

    public void run(){
        process();
    }

    void process(){
        System.out.println("Client " + id + " processing ...");
        try{
            Thread.sleep(1000);
            Thread t1 = new Thread(
                new Runnable(){
                    public void run(){
                        try{
                            test.deposit(c);
                        }
                        catch(InterruptedException ex){
                        }
                    }
                }
            );
            Thread t2 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t3 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t4 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

        /*  Thread t5 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t6 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
            Thread t7 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
            Thread t8 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
        */  
            t1.start();t2.start();t3.start();t4.start();//t5.start();t6.start();t7.start();t8.start();
            t1.join();t2.join();t3.join();t4.join();//t5.join();t6.join();t7.join();t8.join();

        }
        catch(InterruptedException ex){
            System.out.println(" Exception " + ex.getMessage());
        }
        System.out.println("Client " + id + " done #####");
    }
}

}

public void deposit(String clientId){
   String id = clientId;
   while(id.equals("someClientID")){
         synchronized(lockObject){
             // Do your stuff here in a sync'd way
          }
   }
   else
   {
     // Do your stuff here in a NON synch'd way 
   }

 }

Second attempt : ( not tested !)

public void deposit(String clientId){
    String id = clientId;
   // callers is a ConcurrenthashMap<String,String>
     while(callers.get(id) != null){  
     synchronized(callers.get(id)){  // client already in call, so wait
        wait(); 
     }
   }       
      callers.put(id,id);  // client is ready to run a new call, so setup 
      // Do your stuff here in a NON synch'd way 
 synchronized(callers.get(id)){  // client done with a call , 
                      //so notify others who are calling
    callers.put(id,null);
    notifyAll();
       }
}  

Third attempt ( tested and working correctly )

    public class SyncTest {
     static int[] balances = new int[]{ 1,10,100,1000,10000};
public static void main(String[] args) {
    // TODO Auto-generated method stub
    SyncTest test = new SyncTest();
    Client c1 = new Client("0", test,1);
    Client c2 = new Client("1", test,10);
    Client c3 = new Client("2", test,100);
    Client c4 = new Client("3", test,1000);
    Client c5 = new Client("4", test,10000);

    Thread[] threads = new Thread[5];
    threads[0] = new Thread(c1);
    threads[1] = new Thread(c2);
    threads[2] = new Thread(c3);
    threads[3] = new Thread(c4);
    threads[4] = new Thread(c5);

    for(int i=0;i<5;i++){
        threads[i].start();
    }
    for(int i=0;i<5;i++){
        try{
            threads[i].join();
        }
        catch(InterruptedException ex){
        }
    }


    System.out.println("Final balances are ");
    for(int i=0;i<5;i++){
        System.out.print(balances[i] + " , " );
    }
}

ConcurrentHashMap<String,String> callers = new ConcurrentHashMap<String, String>();

public void deposit(Client c) throws InterruptedException{
    String id = c.id;
    int amount = c.amount;
    if(id == null) return ;

   // callers is a ConcurrenthashMap<String,String>
    System.out.println("Client " + id + " in deposit. Checking if already running..");
    while( callers.get(id) != null && !(callers.get(id).equals("X"))) {
       synchronized(id){
        System.out.println("Client " + id + " in deposit. Found already running,going to wait..");
        id.wait(); 
     }
   }
    if(callers == null){
        throw new NullPointerException("Callers is null!!");
    }

    System.out.println("Client " + id + " in deposit. Found not running already,  Now running..");
    callers.put(id,id);
    int index = Integer.parseInt(id);
    balances[index] += amount;
    Thread.sleep(2000);
    synchronized(id){
        String old = callers.put(id,"X");
        id.notifyAll();
       System.out.println("Client " + id + " in deposit. Finished running ,  Notifying..");
    }
}

static class Client implements Runnable {
    String id ;
    SyncTest test;
    int amount;
    Client c = this;

    Client(String id , SyncTest t, int am){
        this.id = id;
        test = t;
        amount = am;
    }

    public void run(){
        process();
    }

    void process(){
        System.out.println("Client " + id + " processing ...");
        try{
            Thread.sleep(1000);
            Thread t1 = new Thread(
                new Runnable(){
                    public void run(){
                        try{
                            test.deposit(c);
                        }
                        catch(InterruptedException ex){
                        }
                    }
                }
            );
            Thread t2 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t3 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t4 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

        /*  Thread t5 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );

            Thread t6 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
            Thread t7 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
            Thread t8 = new Thread(
                    new Runnable(){
                        public void run(){
                            try{
                                test.deposit(c);
                            }
                            catch(InterruptedException ex){
                            }
                        }
                    }
                );
        */  
            t1.start();t2.start();t3.start();t4.start();//t5.start();t6.start();t7.start();t8.start();
            t1.join();t2.join();t3.join();t4.join();//t5.join();t6.join();t7.join();t8.join();

        }
        catch(InterruptedException ex){
            System.out.println(" Exception " + ex.getMessage());
        }
        System.out.println("Client " + id + " done #####");
    }
}

}

〆凄凉。 2024-12-11 23:59:36

肯定不是使用 synchronized 关键字。内置同步原语知道如何在不同线程之间进行判断,仅此而已 - 它们无法根据方法的参数值做出决定。您想要做的是为每个客户端或等效的东西建立一个同步消息队列,并且仅从该队列调用您的函数。

Not with the synchronized keyword, that's for sure. The built-in synchronization primitives know how to adjudicate between different threads and nothing more - they can't make the decision based on the value of parameters to a method. What you want to do is a synchronized message queue for each client or something equivalent, and have your function called only from that queue.

沉睡月亮 2024-12-11 23:59:36

我不同意您的假设,即两个线程可以访问相同的值而无需同步(或以某种方式独占锁定)。

如果发生更新,则必须确保所有更新和读取值的方法都被独占锁定,否则会发生混乱。如果您没有这些锁,那么您可能会得到部分或不正确的结果。

假设您有一个如下流程:

  1. 更新交易列表
  2. 更新余额

线程 1 启动该流程,并执行 1。第二个线程读取(仅读取)交易列表和余额。线程 2 完成该过程并结束。

现在,线程 2 的帐户状态视图不一致。该列表与余额不匹配。这只是一个例子,但却很能说明问题。

无论第一个调用者多次调用该请求还是有多个调用者,都没有关系。对数据的所有访问都需要同步。如果你正在改变某些东西,那么你需要向每个人呈现一致的视图,这意味着同步。

I would disagree with your assumption that two threads can access the same value without both being synchronized (or exclusively locked in some way).

If you have an update happening then you must ensure that all methods for updating AND READING the values are exclusively locked, otherwise chaos ensues. If you don't have these locks, then you can get partial or incorrect results.

Say you have a process like:

  1. Update list of transactions
  2. Update balance

Thread 1 starts the process, and does 1. The second thread READS (just reads) the list of transactions and balance. Thread 2 completes the process, and finishes.

Now thread 2 has an inconsistent view of the state of the account. The list does not match the balance. This is just an example, but it illustrates the problem.

It does not matter whether the first caller calls the request multiple times or you have multiple callers. All accesses to your data need to be synchronized. If you are in the process of changing something, then you need to present a consistent view to everyone, which means synchronizing.

樱娆 2024-12-11 23:59:36

每个客户端使用一个锁。也就是说,不直接同步方法,而是通过锁对象使用显式锁定。进行安排,使每个客户端都有一把锁,用于同步对存款功能的访问。

Use a lock per client. That is, instead of synchronizing the method directly use explicit locking through lock objects. Arrange it such that you have one lock per client which you use to synchronize access to the deposit function.

待天淡蓝洁白时 2024-12-11 23:59:36

你可以这样做:

Client lock = yourClient;
synchronized (lock) {

}

获取客户端上的锁相同的引用。

You can do:

Client lock = yourClient;
synchronized (lock) {

}

Obtain the lock on the client same reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文