Re: How to make this program more efficient?
peter koch wrote:
I still don't get it. Are you telling me that we if we changed to your
structure definition and my thread 1 code to
// thread 1:
result temp(2,func(2));
pres = &temp;
(fullfilling both of your requirements), then thread 2 will always
have a consistent result - without any kind of synchronisation?
No, I'm saying this is thread safe if pointer reads and writes are atomic
but it is non-deterministic.
I say you will not and that you need a memory barrier writing the
pointer (and nothing more).
Assuming you mean "deterministic" when you say "consistent", I think you are
wrong. Even if both the reader and writer lock the pointer (which is
pointless if the operations are already atomic) there is still a race
condition. Specifically, the reader (thread 2) might read either the old or
new value.
For example, the following program can either lock or not lock the reads and
writes as a counter is incremented. As pointer reads and writes are atomic
on this architecture, introducing locks only serves to make the program run
several times more slowly (on this 2x4 core AMD64 machine in x86 mode):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct pair { long long i, j; };
const int readers = 7;
const int max = 1000000;
struct pair * volatile global;
pthread_mutex_t mutex;
void set(int n, int m)
{
struct pair * volatile t = (struct pair *)malloc(sizeof(struct pair));
t->i = n;
t->j = m;
/* Atomic pointer write. */
#ifdef LOCKING
pthread_mutex_lock(&mutex);
#endif
global = t;
#ifdef LOCKING
pthread_mutex_unlock(&mutex);
#endif
}
void *PrintHello(void *threadid)
{
while (0 == 0)
{
struct pair * volatile t;
#ifdef LOCKING
pthread_mutex_lock(&mutex);
#endif
t = global; /* Atomic pointer read. */
#ifdef LOCKING
pthread_mutex_unlock(&mutex);
#endif
int n = t->i, m = t->j;
if (n != m)
printf("Thread %d found error: %d != %d.\n", (int)threadid, n, m);
else
if (n == max)
{
printf("Thread %d exiting.\n", (int)threadid);
pthread_exit(NULL);
}
}
}
int main()
{
pthread_t threads[readers];
int rc, t;
void *status;
pthread_mutex_init(&mutex, NULL);
set(0, 0);
for(t=0; t<readers; t++) {
printf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t=1; t<=max; ++t)
set(t, t);
pthread_mutex_destroy(&mutex);
pthread_exit(NULL);
}
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?u