multithreadinggroovythread-safetythreadpoolgpars

makeConcurrent dosen't seem to work in Gpars


The following program is supposed to return a list of rows which have null values.

import groovyx.gpars.GParsPool
import groovyx.gpars.ParallelEnhancer
import org.apache.commons.lang.RandomStringUtils
import groovyx.gprof.*
import static java.lang.Runtime.*;

def rows = []
def list = []

String charset = (('A'..'Z') + ('0'..'9')).join()
Integer length = 9

for (i in 0..1024) {
    rows[i] = RandomStringUtils.random(length, charset.toCharArray())
}

parallelResult = []
// Parallel execution

GParsPool.withPool(8) {
    parallelResult.makeConcurrent()
    rows.eachParallel {
        if (it[0] != null) {
            parallelResult.push(it)
        }
    }
    parallelResult.makeSequential()
}

// Sequential execution 
sequentialResult = []
rows.each {
    if (it[0] != null) {
        sequentialResult.push(it)
    }
}

assert parallelResult.size == sequentialResult.size

Sometimes, the results are not equal. It is probably because of some issue with makeParallel. If not makeParallel, how do I create concurrent lists using GPars?


Solution

  • I suspect you've introduced a race condition on parallelResult. makeConcurrent() does not prevent race conditions on the collection, it only changes behavior of each(), collect() and such methods.

    If you want to preserve the current design with an accumulator, you'll need to synchronize it or use an agent. You should, however, consider using a more functional approach, in my opinion. Perhaps something like "parallelResult = rows.findAllParallel{it[0]!=null}"