大家再一次!
我正在实现一个计算函数,它运行一大堆数字,因此应该切成所有由单线程计算的小片段。使用少于8个线程& dividable by 2运行okayish(小错误,使用一个线程,所以n_threads = 1,给出正确的结果!)。
问题:“所以我想知道如果我从不访问全局变量,是否需要互斥锁?”
解释现状:我有double sum
然后我创建线程并按部分运行数组计算。
最后,我拿出所有部分金额,并将它们加到主计划中的总和中。然后我添加了数组的其余部分,没有分成线程(例如,在总数组长度为10和4个线程的情况下:这将为线程提供8个数组元素,另外2个必须另外计算) 。我担心,这似乎不是正确的方法。我还没有深入到这个主题,所以我不确定是否必须在某个地方锁定一些访问主程序中的总和。
主码:
double sum = 0;
// arr, p and n_threads are given into this as input to a function
pthread_t threads[n_threads];
struct thread_input thread_args[n_threads];
int thread_size = total_elemts/n_threads;
for (int t = 0; t < n_threads; t++){
thread_args[t].tid = t;
thread_args[t].start = t*thread_size;
thread_args[t].end = ((t+1)*thread_size)-1;
thread_args[t].arr = arr;
thread_args[t].p = p;
thread_args[t].part_sum = 0;
pthread_create(&threads[t], NULL, thread_number, (void*) &thread_args[t]);
}
for (int t = 0; t < n_threads; t++){
pthread_join(threads[t], NULL);
printf("thread %d %15.10lf\n", t, thread_args[t].part_sum);
sum += thread_args[t].part_sum;
}
return sum;
number_thread:
void* thread_number(void* arg){
struct thread_input *param = (struct thread_input*)arg;
int i;
for(i = param->start; i <= param->end; i++){
param->part_sum += Func1(param->arr[i]);
}
for(i = param->start; i <= param->end-1; i+=2){
param->part_sum += Func2(param->arr[i], param->arr[i+1]);
}
for(i = param->start; i <= param->end-3; i+=4){
param->part_sum += Func3(¶m->arr[i], param->p);
}
return NULL;
}
没有锁可以没关系,还是我错过了其他的东西? 谢谢大家!
答案 0 :(得分:2)
pthread_join()
由POSIX(基本定义,4.12内存同步,POSIX在http://pubs.opengroup.org/onlinepubs/9699919799/提供)指定,以使内存与其他线程同步,所以不,你不需要互斥锁,thread_args[t].part_sum
之后thread_number()
pthread_join()
的分配对On Error Resume Next
Dim cn As ADODB.Connection, rs As ADODB.Recordset, r As Long
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Jet OLEDB:Database Password=((*$%&)^#^@; Data Source=C:\z.mdb;"
Set rs = New ADODB.Recordset
rs.Open "Marvin", cn, adOpenKeyset, adLockOptimistic, adCmdTable
With rs
.AddNew ' create a new record
' add values to each field in the record
.Fields("name") = Range("D3").Value
.Fields("field2") = Range("D4").Value
.Fields("field3") = Range("D6").Value
.Fields("field4") = Range("D7").Value
.Update ' stores the new record
End With
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
On Error GoTo 0
MsgBox "Summary Added Successfully.", vbInformation, "Marvin Adams:"
之后的主代码可见。
答案 1 :(得分:1)
不需要锁定,因为 sum 只能在代码的序列部分中访问。
结果中的小误差/变化很可能源于更改求和的顺序,即当您在单个线程中累加总和,并且总和的值变大时,可能会在数字上忽略小的附加值,这可能会累积到一个重大错误。总和部分和首先缓解了这个问题,因此,多线程结果可能更准确。
如果您对代码中的变量进行适当的多线程访问存在疑问,可以考虑在启用thread sanitizer的情况下编译和运行该程序。
作为旁注,在示例代码中没有为成员 param-&gt; buf 分配任何内容。