【发布时间】:2018-06-17 11:46:16
【问题描述】:
我正在尝试使用 OpenMP 来并行化将 Java 字符串数组转换为 C 字符串数组 (char**) 的过程:
char** convert(JNIEnv *env, jobjectArray jstringArray, int n_threads){
int n_rows =(*env)->GetArrayLength(env, jstringArray);
char **cArray = (char **) malloc(n_rows * sizeof(char*));
int i=0;
jstring row;
if(n_threads <= 0 ) n_threads = 1;
#pragma omp parallel for num_threads(n_threads) private(i, row)
for (i=0; i<n_rows; i++) {
row = (jstring) (*env)->GetObjectArrayElement(env, jstringArray, i);
cArray[i] = (char*)(*env)->GetStringUTFChars(env, row, 0);
printf("cArray[%d]: %s thread:%d row:%p env:%p jstringArray:%p\n", i, cArray[i], omp_get_thread_num(), row, env, jstringArray);
}
return cArray;
}
但是,在获取 jstring 行时,我似乎遇到了竞争条件:
n_threads = 1 的输出:
cArray[0]: AA thread:0 row:0x7f5b1c000c90 env:0x7f5b300091f8 jstringArray:0x7f5bb3ffdc38
cArray[1]: BB thread:0 row:0x7f5b1c000c98 env:0x7f5b300091f8 jstringArray:0x7f5bb3ffdc38
cArray[2]: CC thread:0 row:0x7f5b1c000ca0 env:0x7f5b300091f8 jstringArray:0x7f5bb3ffdc38
cArray[3]: DD thread:0 row:0x7f5b1c000ca8 env:0x7f5b300091f8 jstringArray:0x7f5bb3ffdc38
n_threads = 3 的输出:
cArray[0]: AA thread:0 row:0x7f434c004050 env:0x7f434800a9f8 jstringArray:0x7f435b8f0c48
cArray[1]: BB thread:0 row:0x7f434c004060 env:0x7f434800a9f8 jstringArray:0x7f435b8f0c48
cArray[2]: **CC** thread:1 **row:0x7f434c004058** env:0x7f434800a9f8 jstringArray:0x7f435b8f0c48
cArray[3]: **CC** thread:2 **row:0x7f434c004058** env:0x7f434800a9f8 jstringArray:0x7f435b8f0c48
冲突函数似乎是 GetObjectArrayElement(),它为两个不同的线程(示例中的 1 和 2)和 2 个不同的数组索引(2 和 3)返回相同的引用。
这种行为是上述 JNI 函数固有的,还是我遗漏了什么?
【问题讨论】:
-
在私有列表中声明循环变量 i 看起来很可疑。
-
@AlexF 我知道它默认是私有的
-
您只能在已附加到 JVM 的线程上进行 JNI 调用。
-
@AlexCohn 这实际上很有帮助。谢谢。
-
@AlexCohn JRE 8。我已经通过将每个线程附加到 JVM 来修复它。
标签: java multithreading java-native-interface thread-safety openmp