Hello. I am curious if I can have two threads process a shared array in a pipelined manner, and still be thread-safe without using mutex locks:
thread1 advances in the array, doing its work.
thread2 also advances, but stops to wait if the next element is being processed by thread1.
To test that, I wrote a small program.
A writer thread writes into a shared array.
A reader thread reads from the shared array, then prints it in the terminal.
This repeats until 80000 elements have been printed.
I repeated this program many times, and one time the printing paused indefinitely. I suspect there was a deadlock, but I can't reproduce it again.
My question is: can the two threads in this program reach a state of deadlock? If so, can someone explain how it can happen?
edit: I thought this should be fine was because a while ago, I read an article, and it says it is fine as long as each piece of data is written to by only one thread. I kept that in mind and these two threads seem to do just that (at least I think they do).
#include <pthread.h>
#include <stdio.h>
//#include <windows.h>
#include <time.h>
#define DATA_SIZE (80)
// used to stop threads
volatile int running = 1;
// both threads use this share array of data
volatile unsigned data[DATA_SIZE] = {0};
// numbers to show which element a thread is using
volatile unsigned writer_seq = 1, reader_seq = 0;
// numbers to show how many times the threads waited for each other
volatile unsigned long long writer_waits = 0, reader_waits = 0;
// number of iterations the reader thread will run
volatile unsigned reads_left = DATA_SIZE * 1000;
void * writer_thread(void * args)
{
unsigned count = 0;
while(running){
if(writer_seq == 0)
count = (count + 1) % 10;
data[writer_seq] = count;
unsigned next = (writer_seq + 1) % DATA_SIZE;
while(next == reader_seq)
{
writer_waits++;
//Sleep(1);
}
writer_seq = next;
}
return NULL;
}
void * reader_thread(void *args)
{
while(running){
printf("%d", data[reader_seq]);
unsigned next = (reader_seq + 1) % DATA_SIZE;
while(next == writer_seq)
{
reader_waits ++;
//Sleep(1);
}
reader_seq = next;
reads_left--;
if(reads_left == 0)
running = 0;
}
return NULL;
}
int main(void)
{
clock_t t1 = clock();
pthread_t writer, reader;
pthread_create(&writer, NULL, &writer_thread, NULL);
pthread_create(&reader, NULL, &reader_thread, NULL);
void * ret = NULL;
pthread_join(writer, &ret);
pthread_join(reader, &ret);
clock_t t2 = clock();
printf("reader waits:%llu, writer waits:%llu, time:%f\n", reader_waits, writer_waits, (float)(t2 - t1) / CLOCKS_PER_SEC);
}