How many variables can a mutex lock in a critical section? - c

let's assume for example i have this piece of code
#include <phtreads.h>
int var1 ;
int varn;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *thread1
{
//start critical section1
pthread_mutex_lock(&mutex);
edit var 1
edit var n
pthread_mutex_unlock(&mutex);
//end critical section1
}
void *thread2
{
//start critical section2
pthread_mutex_lock(&mutex);
edit var 1
edit var n
pthread_mutex_unlock(&mutex);
//end critical section2
}
how many variables can i edit in the critical section ?
only 1 variable or how many i want?
assume this is pseudo code

A mutex does not lock any variables.
All it does is block threads from proceeding while another one has the mutex locked. The threads are blocked in the pthread_mutex_lock call until the system can grant the lock to thread.
So the number of variables is unlimited, but for your sanity (and your programs correctness) make sure you know what variables require what mutex to be locked.

Related

Using different mutex locks in threads

I have written the following program to implement two threads in POSIX. There is a global shared variable sum, which is being accessed by two different threads simultaneously. I have used mutex lock and unlock inside each thread while accessing the shared variable. I have a question. Here I have used the samed mutex lock (pthread_mutex_lock(&mutex))inside the two threads. What will Happen if I use two different mutex lock and unlock inside the threads (such as pthread_mutex_lock(&mutex)) in thread1 and pthread_mutex_lock(&mutex1) in thread2. I have commented out the line of confusion in the code.
My sample code fragment:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex1=PTHREAD_MUTEX_INITIALIZER;
int sum=0;
void * threadFunc1(void * arg)
{
int i;
for(i=1;i<100;i++)
{
printf("%s\n",(char*)arg);
pthread_mutex_lock(&mutex)
sum++;
pthread_mutex_unlock(&mutex)
sleep(1);
}
}
void * threadFunc2(void * arg)
{
int i;
for(i=1;i<100;i++)
{
printf("%s\n",(char*)arg);
pthread_mutex_lock(&mutex) //what will happen if I use mutex1 here
sum--;
pthread_mutex_lock(&mutex) //what will happen if I use mutex1 here
sleep(1);
}
}
int main(void)
{
pthread_t thread1;
pthread_t thread2;
char * message1 = "i am thread 1";
char * message2 = "i am thread 2";
pthread_create(&thread1,NULL,threadFunc1,(void*)message1 );
pthread_create(&thread2,NULL,threadFunc2,(void*)message2 );
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
return 0;
}
What is the basic difference between using the same mutex locks and different mutex lock in accessing a shared variable?
The purpose of the mutex is to prevent one thread from accessing the shared variable while another thread is, or might be, modifying it. The semantics of a mutex are that two threads cannot lock the same mutex at the same time. If you use two different mutexes, you don't prevent one thread from accessing the shared variable while another thread is modifying it, since threads can hold different mutexes at the same time. So the code will no longer be guaranteed to work.

Giving mutex to correct thread

If two threads are being blocked on a lock, how can you choose which get's it?
For example thread1 calls mutex_lock(aMut) but aMut is already locked so thread1 blocks. Along comes thread2 and it calls mutex lock on aMut and it blocks. How can it be ensured aMut is given to thread2?
here is my attempt that doesn't work
/*global variables*/
pthread_mutex_t aMut = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIIALIZER;
pthread_cond_t changeNumPrior = PTHREAD_COND_INITIIALIZER;
int highPriorityThreads = 0;
/*function that is passed to pthread_create()*/
void* functionThatIsPassedToPthreadCreate(void* arg)
{
bool highPriority = false;
if(arg->someConditionIsMet)
{
highPriorityThreads++;
highPriority = true;
}
pthread_mutex_lock(&changeNumPrior);
while(!highPriority && highPriorities > 0)//this doesn't work
{
pthread_cond_wait(&cond_var, &changeNumPrior);
}
pthread_mutex_unlock(&changeNumPrior);
pthread_mutex_lock(&aMut);//if this blocks, by the time this mutex is aquired, there now may be high priority threads
//code that requires exclusive access to shared resource protected by aMut
pthread_mutex_unlock(&aMut);
pthread_cond_signal(&cond_var);
}
Just saying "Now I want this task to be scheduled and now this one" is not possible, but some thread libraries allow to set the priority of tasks, so it will be favored when scheduling.
For pthreads, you can do this with pthread_getschedparam.

Recreate sem_wait() with mutex?

Is there any way so I can have up to 10 threads in the same mutex?
Something like sem_wait() with value 10.
Edit:
Found this:
it is an implementation of semaphores, using mutexes and condition variables.
typedef struct {
int value, wakeups;
Mutex *mutex;
Cond *cond;
} Semaphore;
// SEMAPHORE
Semaphore *make_semaphore (int value)
{
Semaphore *semaphore = check_malloc (sizeof(Semaphore));
semaphore->value = value;
semaphore->wakeups = 0;
semaphore->mutex = make_mutex ();
semaphore->cond = make_cond ();
return semaphore;
}
void sem_wait (Semaphore *semaphore)
{
mutex_lock (semaphore->mutex);
semaphore->value--;
if (semaphore->value < 0) {
do {
cond_wait (semaphore->cond, semaphore->mutex);
} while (semaphore->wakeups < 1);
semaphore->wakeups--;
}
mutex_unlock (semaphore->mutex);
}
void sem_signal (Semaphore *semaphore)
{
mutex_lock (semaphore->mutex);
semaphore->value++;
if (semaphore->value <= 0) {
semaphore->wakeups++;
cond_signal (semaphore->cond);
}
mutex_unlock (semaphore->mutex);
}
See If that Helps
From Book Begining Linux programming a counting semaphore that
takes a wider range of values. Normally,semaphores are used to
protect a piece of code so that only one thread of execution can run
it at any one time. For this job a binary semaphore is needed.
Occasionally, you want to permit a limited number of threads to
execute a given piece of code; for this you would use a counting
semaphore
No, A mutex is a simple lock, having two states: locked and unlocked. When it is created, a mutex is unlocked. A mutex is a mutual exclusion lock. Only one thread can hold the lock.
Although you can implement to allow ten threads to enter in a section using mutex and if and a global variable. (the way count semaphores are implemented)
Read here: Implementing a Counting Semaphore
One Available implementation: C code , Make your own semaphore

pthread_mutex_lock causes deadlock

I am using the above code to increment a counter using 2 threads, which independently take the mut lock and increment counter. I am facing a deadlock after the threads enter this function.
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
for(iter=0;iter< max ;iter++)
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
return NULL;
}
Could anyone please tell me where exactly am I going wrong?
You're trying to lock the mutex max times, then increment counter and release it once.
Try:
for(iter=0;iter< max ;iter++)
{
// LOCK
pthread_mutex_lock(&mut);
counter++;
// UNLOCK
pthread_mutex_unlock(&mut);
}
return NULL;
That is maybe what you tried to do:
int max = MAX_COUNTER_VALUE;
int iter;
int counter;
pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
void *increment_counter(void *counter_addr)
{
pthread_mutex_lock(&mut);
for(iter=0;iter< max ;iter++)
counter++;
pthread_mutex_unlock(&mut);
return NULL;
}
2 or more threads share only global scope data or data located on the
heap(malloc).
2 or more threads do not share variables defined on the stack this
data is unique to each thread and there is no need to lock it.
You are welcomed to read in the answers what is shared and what is not shared etc.
As a principle, the same thread should not lock a mutex more than once and that's what happened here.
lock initialization is very important. If you don't initialize your locks to the right value your code breaks. One method for initializing your lock is the following:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Also you can do this task dynamically by using the following code:
int rc = pthread_mutex_init(&lock, NULL);
assert(rc == 0); // always check success!
Beside lock initialization, you should check for the return code of pthread_mutex_lock to see if it fails or not as if it fails, multiple thread can enter the critical section. For this purpose, you can use a code similar to this which checks for the return code of pthread_mutex_lock:
// Use this to keep your code clean but check for failures
// Only use if exiting program is OK upon failure
void Pthread_mutex_lock(pthread_mutex_t *mutex) {
int rc = pthread_mutex_lock(mutex);
assert(rc == 0);
}

Sharing one buffer - thread safe

I am not much into scheduling threads, i have like 4-5 threads and each of them will add data to one same buffer at random time.
How i can schedule the threads so there is no case two or more threads to access the buffer at same time ?
I am coding in C on Windows environment.
Thanks in advance.
The shared buffer needs to be protected from concurrent reads/writes by different threads. A synchronization object should be used to prevent this from occuring. Anytime a thread wants to read from or write to the shared buffer it would acquire the lock, perform its operations on the shared buffer and release the lock once it no longers requires the buffer.
An example synchronization object would be CriticalSection:
static CRITICAL_SECTION shared_buffer_lock;
static char shared_buffer[10];
int main()
{
InitializeCriticalSection(&shared_buffer_lock);
/* Start threads */
...
/* Wait for threads */
...
DeleteCriticalSection(&shared_buffer_lock);
return 0;
}
/* In thread.. */
/* Obtain sole access to 'shared_buffer' */
EnterCriticalSection(&shared_buffer_lock);
/* Use 'shared_buffer' ... */
/* Release sole access of 'shared_buffer' */
LeaveCriticalSection(&shared_buffer_lock);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int sharedData=0;
void *func(void *parm)
{
int rc;
printf("Thread Entered\n");
pthread_mutex_lock(&mutex);
/********** Critical Section *******************/
printf("Start critical section, holding lock\n");
++sharedData;
printf("End critical section, release lock\n");
/********** Critical Section *******************/
pthread_mutex_unlock(&mutex);
}
The example above shows what you are looking for, using pthreads library. Acquire the mutex with pthread_mutex_lock and release it with pthread_mutex_unlock. All threads that request the same lock will be blocked until mutex is released. This guarantees that only one thread has access to your shared data.
You need to implement an exclusive access to the ressource (buffer). Under Windows I would use Mutexes for it (see CreateMutex and WaitForSingleObject/WaitForMultipleObjects in Windows API).

Resources