1

Background: I am running automation tests in parallel. Multiple browsers get launch in the same number of threads i.e. 1 browser is 1 thread, using forking in pom.xml.

Below plugin in pom.xml creates an equal number of Parallel**IT.class as thread(fork) count is.
All these classes are executed at once parallel. So, it seems whenever I create a volatile variable or AtomicInteger each thread creates its own of these and so concept sharing a variable across multiple threads is not working.

                <plugin>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>${maven.failsafe.plugin}</version>
                        <configuration>
                            <systemPropertyVariables>
                                <webdriver.base.url>${webdriver.base.url}</webdriver.base.url>
                                                                </systemPropertyVariables>
                            <argLine>
                                -javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
                            </argLine>
                            <forkCount>5</forkCount>
                            <reuseForks>true</reuseForks>
                            <includes>
                                <include>**/Parallel*IT.class</include>
                            </includes>
                            <perCoreThreadCount>true</perCoreThreadCount>
                            <properties>
                                <property>
                                    <name>listener</name>
            <value>ru.yandex.qatools.allure.junit.AllureRunListener</value>
                                </property>
                            </properties>
                        </configuration>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>


I want only 1 thread to access the "prepare test data" function and set flag to false, when other threads see flag as false they do not attempt to prepare test data.

I am following a tutorial https://www.youtube.com/watch?v=WH5UvQJizH0 to implement synchronization using a volatile variable. Maybe I am making some mistake, but all threads are printing System.out.println("Preparing test data");

Try 1: Volatile and Synchronization

volatile boolean flag = false;

    public synchronized void setFlagTofalse(){
        System.out.println("Inside sync block");
          this.flag = true;
    }
    // works before class only once
    private EventHandler<TestRunStarted> prepareTestData = event -> {
            if(flag==false) {
                System.out.println("Preparing test data");              
                setFlagTofalse();
            }
    };

Try 2: Atomic and Synchronization

AtomicInteger flag = new AtomicInteger(0);

    private EventHandler<TestRunStarted> prepareTestData = event -> {
        if(flag.get()==0) {
            System.out.println("Preparing test data");
            value.incrementAndGet();
        }
8
  • Please update your question with a minimal reproducible example. Your various comments that some of the answers are not working indicate some context is missing. Commented May 23, 2019 at 11:36
  • What context is missing? I'll try to update, please at least put your guesses. Commented May 23, 2019 at 11:39
  • For one, the class that contains these flags and methods. How they are called or started, etc. Commented May 23, 2019 at 11:40
  • That's obvious in case of multithreading and parallel execution but still, let me put it in question description. Commented May 23, 2019 at 11:43
  • That is not obvious, otherwise I wouldn't ask. All answers here are assuming that this is a single instance that will be shared by all threads, but that doesn't seem to be the case. Commented May 23, 2019 at 11:47

4 Answers 4

1

If I were you I would implement the a Mutex lock, when accessing the flag variable. So before reading the value of the flag, or changing its value, the thread has to acquire the lock. This way they never read it at the same time or write a new value while an old one is till being read etc.

EDIT: More explanation

@paul To explain what the lock does: It is basically a ball that can be tossed around by threads. So if you sit in a circle with a group of people, and you have the ball it is your turn to speak about "X". Then once you are done speaking you put the ball in the middle of the circle, and it remains there till the same person or someone else wants the ball again and takes it or waits till it is available and may then speak about "X". In your case a thread must have the lock to change or read the variable flag, so what you would do is:

Mutex lock = new Mutex();
lock.aquire();
if ( flag == something ){
    //do something
}
mutex.release()

or if you are changing the flag.

lock.aquire();
flag = something;
lock.release();

As you can see the lock is shared between threads. So it is created in the class that manages the threads, and passed on to the Runnable Objects or methods that are started in the threads.

So:

Mutex lock = new Mutex();
Runnable1 r1 = new Runnable1(lock);
Runnable2 r2 = new Runnable2(lock);
//use the lock in the methods of t1 and t2 that use your volitile var
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1.start();
t2.start();

//the join wait for completion of the runnable method in your class.
t1.join();
t2.join();

Good luck :)

Sign up to request clarification or add additional context in comments.

5 Comments

If thread don't get the data, it would fail the test. I don't want that. Hey, but mutex lock is something I never heard about. If you could share the snippet, it would be great learning.
@paul mutex is nothing more then a lock... your synchronized is already a mutex on the Object instance
What @Eugene says it true, but sometimes i prefer to see the methods of the lock actually being used.
@BasvanderLinden which api is this, is this import org.jruby.ext.thread.Mutex;?
@paul import java.util.concurrent.Semaphore, A semaphore is like mutex lock, but you can decide how many threads can access the lock. Scroll down to section 2, on the link below. Read: mkyong.com/java/java-thread-mutex-and-semaphore-example
0

If you do a test (flag.get()==0) and an action, you have two synchronize both of these things. Just mark your whole prepareTestData-method as synchronized?

Comments

0

You have synchronized the wrong method. You could try something like this instead:

volatile boolean flag = false;

public void setFlagTofalse(){
    System.out.println("Inside sync block");
    this.flag = true;
}
// works before class only once
private EventHandler<TestRunStarted> prepareTestData = event -> prepareData();

private synchronized void prepareData() {
    if(!flag) {
        System.out.println("Preparing test data");
        setFlagTofalse();
    }
    //prepare data here
}

4 Comments

@paul If that didn't work, then you need to update your code with a minimal reproducible example, because that would imply that each thread has its own flag and/or its own monitor to synchronize on.
@MarkRotteveel every time you comment, it looked it's very valuable but I can't comprehend. This time also I didnt get.
@paul That suggests that you really need to brush up on your concurrency and multi-threading knowledge.
If I knew why would I ask? If I want to brush-up/improve/learn I need to implement and when we implement, we get stuck and when we stuck we ask the question and when we supposed to ask a question we think of best forums available and so here we are.
0

The "flag" and "lockObject" needs to be "static" so that you will have only one instance for each object. Although if you have singleton object then you don't have to use "static" for "flag" but "lockObject" should be static.

Also, synchronize using "lockObject" inside "prepareTestData". This indicate java that only one thread should be accessing the code beyond this point. Once one thread goes inside, others will be waiting for that thread to return before going in.

private static Object lockObject = new Object();
private static Boolean flag = Boolean.FALSE;

private void prepareTestData() {
   synchronized(lockObject) { //This will keep other threads waiting
      if(!flag) {
          //prepare data
          flag = Boolean.TRUE;
       }
   }
}

Hope this will answer your question.

9 Comments

The flag doesn't need to be static. That would depend on context not shown in the question. And you definitely shouldn't be using Boolean instead of boolean.
@punit do I need tell other's thread to wait like Thread.sleep or these will wait on their own? How they will come out of wait? I have tried Sofo Gial's answer which didnt work, maybe because it doesnt have static idea. Let me try using static.
@MarkRotteveel as mentioned in the answer, flag need to be static if each thread has its own object and calling prepared data. If its singleton then its not. Didn't got your statement regarding Boolean
@paul java takes care of queuing threads. if synchronized is not working then let me edit my answer to use object based locking.
@PunitTiwan. Yeah, this is not Queueing or Sequential it's parallel all are running in parallel. Thanks, appreciate it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.