Concurrent programming with multiple threads waiting for retry

In the requirement design, it is necessary to prevent concurrent processing from being duplicated, resulting in data inconsistency. It can be achieved by using a lock + wait for retry mechanism. The following is an example of simulating this kind of demand. I am using ReentrantLock, a lightweight lock based on AQS, but if it is a distributed system, it is not suitable. In a real scenario, I use redis to implement it. Distributed locks mainly use the atomic method set (NX+PX) of jedisCluster, which is not introduced here.

Not much nonsense, just look at the code:

 public static void main(String[] args) {
        CorpServicePayRecordEntity servicePayRecord = new CorpServicePayRecordEntity();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {

                System.out.println(pout(5, servicePayRecord));
            }
        });
        t1.start();
        t1.setName("thread1");
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(pout(5, servicePayRecord));
            }
        });
        t2.setName("thread2");
        t2.start();


    }

    private static final ReentrantLock LOCK = new ReentrantLock();

    private static String pout(int retry, CorpServicePayRecordEntity servicePayRecord){

            System.out.println("线程"+ Thread.currentThread().getName() + "尝试");
                if(LOCK.tryLock()){
                    System.out.println("线程"+ Thread.currentThread().getName() + "获取成功");
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        LOCK.unlock();
                    }
                    return Thread.currentThread().getName();
                }else {
                    try {
                        Thread.sleep(2000L);
                        retry--;
                        if(retry > 0){
                            return pout(retry, servicePayRecord);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }



        return "nothing";
    }

It means that if the thread acquires the lock, it will execute the output, and other threads will wait for the lock and retry (you can set the number of times). Here, sleep is used to simulate the execution time. When the thread is executed, the lock will be released, and other threads will have a chance. If the object lock is acquired, execute it, otherwise continue to wait for retry.

There is a place to pay attention to here, that is, return. When I just started the test, I found that the second thread could not print out its thread name after acquiring the lock (return Thread.currentThread().getName();). This step is to It's right to print out the thread name, but it can't be printed, it always prints the last nothing. Later, I found out that return pout(retry, servicePayRecord); didn't add return at the beginning, and it was speechless. I thought it was unnecessary if there was a return. In fact, it would be clear to understand the memory structure of jvm, and this may be ignored.

Guess you like

Origin blog.csdn.net/huangdi1309/article/details/88867014