1

Suppose there are two type of concurrent threads, lets say writer and reader (where the reader thread reads the different elements after they are written by the writer).

The writer has the following functions:

+create element (suppose there are 3 types of elements)

+increase element stock (it should be done separately after the creation phase)

The reader has the following function:

+Iterate over the whole database reducing by one unit the element stock until every single inserted element has stock 0 (including the stock after the increase stock phase)

Each element has two variables:

+stock (integer)

+internal data (void pointer) --> Can be used as the programmer wishes in order to achieve syncronization

In order to avoid race conditions, pthread_mutex and pthread_cond_wait functions are used.

My approach to solve this problem concurrently is the following:

write
    pthread_mutex_lock(&mutex)
    set_internal_data(element_id, 1)
    create_element(element_id)
    pthread_cond_signal(&inserted,&mutex)
    pthread_mutex_unlock(&mutex)

    pthread_mutex_lock(&mutex)
    set_internal_data(element_id, 1)
    get_stock(element_id, prev_element_stock)
    update_stock(element_id, prev_element_stock+ element_stock)
    pthread_cond_signal(&inserted,&mutex)
    pthread_mutex_unlock(&mutex)

read
    get_internal_data(element_id, element_internal_data)
    while(element_internal_data)
        pthread_cond_wait(&inserted,&mutex)
    read operation

Note: every created element has 1 unit of stock. Before update_stock, it could happen that the reader reduces this element by one unit but this would not imply that the element is deleted from the database

My questions are:

1) Do you guys think this is the most efficient way to use the internal data variable in order to synchronize the operations?

2) The write operations are inside mutexes but the cond_wait operation is not inside a mutex. Would it be strictly neccesary to have this cond_wait operation inside a mutex?

qwerty
  • 486
  • 1
  • 11
  • 37
  • 1
    Fyi, it isn't shown, but the `read` block had better own the mutex going in to that `pthread_cond_wait. The api` *requires* you own the mutex before invoking it. It releases the mutex *and* begins waiting on the cvar atomically (as far as you're concerned) and, when returning without error, will have the mutex latched again. – WhozCraig May 02 '15 at 20:03
  • And you also have two too many `pthread_mutex_unlock(&mutex)` in your write code. You don't "unlock" what you didn't lock (which can happen multiple ways, such as coming out of a `pthread_cond_wait`. I think you may have a disconnect on something fundamental. the mutex isn't for protecting the `cvar`. its for protecting the *predicate data* from concurrent access. the `cvar` is just a gloarified signalling mechanism. [This may help](https://stackoverflow.com/questions/14924469/does-pthread-cond-waitcond-t-mutex-unlock-and-then-lock-the-mutex/14925150#14925150). – WhozCraig May 02 '15 at 20:07

1 Answers1

1

It is necessary that the read function holds a mutex if you want the thread to block until there is something to read or if you intend to change in any way the shared state. The goal of pthread_cond_wait is to block a thread, release the mutex it holds until a specific condition is met (in your case something is writen) which is notified by using pthread_cond_signal or pthread_condition_broadcast, afterwards it will reaquire the mutex and go on with the read.

For the write operation I think you have typos in the name of the functions but the functions should look like:

pthread_mutex_lock(&mutex)
write_to_the_shared_state
pthread_cond_signal(&cond) / pthread_cond_broadcast(&cond)
pthread_mutex_unlock(&mutex)

and for the read

pthread_mutex_lock(&mutex)
while(data = try_to_read)
    pthread_cond_wait(&cond, &mutex)
pthread_mutex_unlock(&mutex)
return data

This does not include error checking. And if you both write / read to be blocking you will have to mix both example above.

OAnt
  • 131
  • 1
  • 4
  • The problem is that it should only block the read thread that is trying to access the element that is being modified at that moment, but in case the elements that are being read at that time are not being modified, it should be possible to access them concurrently and not doing it one by one through the mutex operation. – qwerty May 02 '15 at 21:25
  • Then you could use this solution to protect each of the element or if there is to many elements to protect use some kind of producer consumer architecture where read/write are sent using message queue. In the latter case the queue should be protected too using the mecanism I described. The goal of the while is to: try to read, if there is nothing block and wait otherwise return. – OAnt May 02 '15 at 21:33
  • Also note that pthread_cond_wait will release the mutex and allow another thread to initiate a read if nothing else has aquired the mutex. – OAnt May 02 '15 at 21:42
  • 1
    @user1920212: "*but in case the elements that are being read at that time are not being modified,*" you might be looking for a read/write lock. For details please see the `pthread_rwlock*()` family of functions. – alk May 03 '15 at 11:53