Program Code

Read this chapter to find out the cause of the detailed source code error. If you want to skip, directly go to solution...

let’s check the code.

ConcurrencySample Code is written in Java, Gradle.

This code has a problem.

  1. This is the structure of the source code.

    -src
        -main/java/com/example/concurrencysample
            -BasicCHeckMap.java
            -BasicSynchronization.java
            -Concurrency.java
            -ConcurrencyCheckout.java
            -SingletonRepo.java
            -Util.java
        -test/java/com/example/concurrencysample
            -SingletonRepoTests.java
    
  2. let’s take a check the SingletonRepo file. SingletonRepo can only have one instance in the program. And sigletonsrepo have one HashMap. let’s check the putKey() function, which is the core of this class and lab.

    public Concurrency putKey(int product_code ) {           
        Date date = Util.getRandomDate();
        if (map.containsKey(product_code)) {
            return map.get(product_code);
        }else{
            return map.put(product_code, new Concurrency(product_code,"test" , date));
        }   
    }
    

    putKey works is simple. Check that HashMap has a number with containsKey() and if not, save the number with put().

    source01

  3. If the HashMap already has the same value, don’t put it. source01

  4. BasicSynchronization calls pukey() of SingletonRepo and inserts a randomly generated number between 0 ~ 2000.

  5. ConcurrencyCheckout is Main class. This class creates 5 BasicSynchronizations and starts 5 threads. source

  6. this program repeats input to one HashMap by 5 threads.


So what is the problem with this program?

  1. This code has a concurrency issue. if it call two PutKey() from two threads at the same time. What will happen? problem0

    The putkey() of both threads will enter the same number in the HashMap and increment the Call Count.

    if (map.containsKey(product_code)) { 
        return map.get(product_code);
    }else{
        return map.put(product_code, new Concurrency(product_code,"test")); <-----first, second threadn function doing.
    }
    
  2. The number is entered only once, but the call count is increased twice.

  3. HashMap is not thread-safe. The code above is dangerous because get and put don’t guarantee atomicity.

  4. If the number of threads is increased and the number of put calls executed simultaneously increases, the result cannot be guaranteed.

  5. An error occurs because the same problem appears in the UnitTest being executed. SingletonRepotests, a unit test that is performed, creates 8 threads and raises the count one by one when an input occurs in the HashMap. And after all the work is done, the number of values entered in the HashMap is compared with the number of occurrences. If the values are the same, the number of inputs and the number of HashMaps are the same, so the function worked correctly.

  6. However, UnitTest will continue to fail because the current code was programmed without considering concurrency. Of course, if you are very lucky, the test may succeed. However, to prevent this, SingletonRepotests performs the same test 100 times.

So how do you solve this problem?