Use mutex or not in a concurrent reading - c++

I am programming in C++ in Linux and I am using pthreads library. I am using mutex to protect some shared variables but I am not sure if in this specific case it is necessary the use of mutex.
I have 3 threads. The shared variable is a string (global variable).
Thread1 changes it's value and afterwards, thread2 and thread3 read it's value and store in another string.
In this case, the string's value is only modified by one thread. Is still necessary the use of mutex to protect a shared variable in a concurrent read by two threads?

"Thread1 changes it's value and afterwards ..." -- if "afterwards" means that the other threads are created after the change, there's no need for a mutex; thread creation synchronizes memory. If it means anything else then you need some form of synchronization, in part because "afterwards" in different threads is meaningless without synchronization.

What you should use is a shared_mutex (get it from boost if you don't want to use C++14/17) (for C++14 there's a shared_timed_mutex that you could use). Then, you do a shared_lock if you want to read the string, and you do a unique_lock if you want to write on it.
If two shared locks meet, they don't collide and they don't block, but a shared lock and a unique lock collide and one of the locks blocks until the other finishes.

Since you are using pthreads, you can use a pthread_rwlock_t.
For updating the object, it would be locked using pthread_rwlock_wrlock() to get a write lock; all readers would access the object only after obtaining a shared read lock with pthread_rwlock_rdlock(). Since the write lock is exclusive, and the read lock is shared, you'd get the behavior you desire.
An example of the use of pthread_rwlock_t read/write locks can be found at http://www.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.genprogc/using_readwrite_locks.htm.
A good summary of the available calls for use on a pthread_rwlock_t lock can be found at https://docs.oracle.com/cd/E19455-01/806-5257/6je9h032u/index.html. I've reproduced the table listing the operations:
Operation
Initialize a read-write lock "pthread_rwlock_init(3THR)"
Read lock on read-write lock "pthread_rwlock_rdlock(3THR)"
Read lock with a nonblocking read-write lock "pthread_rwlock_tryrdlock(3THR)"
Write lock on read-write lock "pthread_rwlock_wrlock(3THR)"
Write lock with a nonblocking read-write lock "pthread_rwlock_trywrlock(3THR)"
Unlock a read-write lock "pthread_rwlock_unlock(3THR)"
Destroy a read-write lock "pthread_rwlock_destroy(3THR)"

Related

Is a mutex capable of performing this

I have a situation where I have multiple threads accessing the clipboard and performing an action with some sleeps. Basically I don't want to copy the wrong thing to the clipboard and perform something in an incorrect fashion.
Currently, I have an idea of using a mutex to lock a std::string variable and store the required data in it, then to the clipboard. After I finish the action, I unlock it. Then the other thread accesses the variable, then clipboard, and action.
As I have never used a mutex, my question is - will it work by just doing the above?
I'm using the following library to manage the clipboard: https://github.com/dacap/clip
From a quick look at the library, you may not need to use a mutex at all. For eg. the set_text function:
bool set_text(const std::string& value) {
lock l;
if (l.locked()) {
l.clear();
return l.set_data(text_format(), value.c_str(), value.size());
}
else
return false;
}
You can see that a lock is being created (which locks the resource based on the os implementation at construction of lock l) which should provide you some thread safety.
Currently, I have an idea of using a mutex to lock a std::string variable and store the required data in it, then to the clipboard.
From the way you explain this it is clear you do not understand how it works. Mutex does not lock a variable whatever type it has. Mutex is locked itself. And mutex has a property that only one thread can lock it at a time. Using that property you can organize your program the way so only one thread will access some critical data and that will make such access thread safe. It is not that you link a mutex to an unrelated variable, then that mutex would somehow lock that variable and make it thread safe. Now if you understand what is different btw those you would understand that yes you can make access to your std::string variable thread safe but that will require all threads accessing it doing that under mutex lock, not that only one thread locks it and all other will obey that lock magically.

pthreads locking scheme to allow concurrent reads of a shared data structure

Let's say you have some code that both reads and writes to a data structure. If you have multiple threads executing this code (and sharing the data structure), is there some arrangement that would achieve the following:
Allow 2 or more concurrent reads, with no writes
Disallow 2 or more writes
Disallow 1 or more reads concurrently with 1 or more writes
A single mutex that is locked during any read and any write achieves goals 2 and 3, but fails to achieve goal 1. Is there some solution that achieves all three goals?
Assume that it is not possible to devise a scheme where different sub-sections of the data structure can be protected with different mutexes.
My clunkly approach to this is:
Have one mutex per thread, and each thread locks its own mutex when it needs to read.
Have one additional 'global' mutex. When any thread wants to write, it first locks this global mutex. Then it goes through a loop of pthread_mutex_trylock() on all of the thread-specific mutexes until it has locked them all, then performs the write, then unlocks them all. Finally, it unlocks the global mutex.
This approach seems to be likely not very efficient, however.
Thanks in advance,
Henry
Pthreads includes reader-writer locks that have this behaviour. You initialise them in an analagous way to mutexes - either statically:
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
or dynamically with pthread_rwlock_init().
To lock for reading (shared) you use pthread_rwlock_rdlock(), and to lock for writing (exclusive) you use pthread_rwlock_wrlock(). There are also "trylock" and "timedlock" variations of these.
You can, of course, also build such a lock from pthreads mutex and condition variables. For example, you could implement the reader-side lock as:
pthread_mutex_lock(&mutex);
readers++;
pthread_mutex_unlock(&mutex);
The writer-side lock is:
pthread_mutex_lock(&mutex);
while (readers > 0)
pthread_cond_wait(&mutex, &cond);
The reader-side unlock is:
pthread_mutex_lock(&mutex);
if (--readers == 0)
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
And the writer-side unlock is:
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
(This is just for interest's sake - you are better off using the built-in reader-writer locks, because those can be implemented directly using architecture-specific code which may well be more efficient than using the other pthreads primitives).
Note also that in a real implementation you would want to consider the case of readers overflowing.

Use lock-free algorithm for shared memory

I want to use lock-free algorithm for shared memory for avoiding mutex. I have some processes that share data use shared memory. If a process is locking mutex and crashes, all other processes also crash.
I read some papers which implement lock-free algorithm with linked list. But in my shared memory, I can't define data structure for using on this block of memory. I have just a pointer to this block.
So I don't have any ideas for apply lock-free algorithm in my situation. I need some helps from you. Thanks and sorry if my English is very bad.
If a process is locking mutex and crashes, all other processes also crash.
Specifically for this use case there are robust mutexes:
PTHREAD_MUTEX_ROBUST
If the process containing the owning thread of a robust mutex terminates while holding the mutex lock, the next thread that acquires the mutex shall be notified about the termination by the return value [EOWNERDEAD] from the locking function. If the owning thread of a robust mutex terminates while holding the mutex lock, the next thread that acquires the mutex may be notified about the termination by the return value [EOWNERDEAD]. The notified thread can then attempt to mark the state protected by the mutex as consistent again by a call to pthread_mutex_consistent(). After a subsequent successful call to pthread_mutex_unlock(), the mutex lock shall be released and can be used normally by other threads. If the mutex is unlocked without a call to pthread_mutex_consistent(), it shall be in a permanently unusable state and all attempts to lock the mutex shall fail with the error [ENOTRECOVERABLE]. The only permissible operation on such a mutex is pthread_mutex_destroy().

Writing to a mutex'ed shared resourced

I've a C++ list which is being processed by multiple thread.
Each thread creates a pthread_mutex_lock on the list so that other threads cannot "interfere" with the list. As a part of processing, each thread also push_back data on the list.
My question is - is push_back on a mutex-ed list a bad idea? Is the mutex still valid while the thread is pusing more data on the list? Most of the documentation/examples I've seen on pthread_mutex_lock are only doing "reading" so I am curious to know what happens the same thread which acquired lock, writes on the shared resource.
As long as only that particular thread is holding the lock, and no other thread can take this lock, writing should be fine. think of why a problem could happen? it wouldve been a problem if one thread was writing and the other was reading simultaneously. If a ball is yours, you can do anything with it right? things change when they're shared.
The mutex needs to be unique for the entire group of threads (i.e. all threads must use the same mutex). If you create a mutex for each thread, then you are not thread-safe at all, because each thread will wait on its own mutex and not be synchronized with the rest.
And yes an acquired mutex can be used safely to both read and write.

Named process internal mutexes with C/C++?

Are there ways to implement named process internal mutexes using C/C++ (in Unix/Linux)?
The trick is that the mutexes lifetime would need to be process persistent. Unlike for example the named posix semaphores and shared memory.
You could have for example pthread mutexes, in a dynamic map and access them with some id. But then you need to protect the mutexes somehow.
If you use memory mapped files or shared memory, you get the filesystem persistence...
Any ideas?
You can always revert back to the older (albeit depreciated) System V semaphores which work off a common key-value rather than a POSIX named semaphore which has file-system persistence. That being said, a POSIX named semaphore will not have file-system persistence if you close and then unlink the semaphore in every process using it. Once the last process that was using the semaphore has exited, the semaphore reference will be removed from the file-system. If you're worried about the visibility of the semaphore at the file-system level, you can always precede the name of the semaphore with a "." in order to make the file invisible, and/or adjust the permissions on the file so that only the current user or some privileged user/group can access the semaphore.
What do you mean by "process-persistent"? If you want them to persist after the process ends, just use named semaphores or named shared memory, and prefix the name with something unique to your program. If you want them to go out of existence when the process terminates, just use any kind of hash map protected by an rwlock (locked in read mode to lookup existing names, write mode to add/remove names).
It's quite simple. Have a mapping of strings to mutexes, and a mutex to protect this mapping:
std::map<std::string, pthread_mutex_t *> mutexMap;
pthread_mutex_t mutexMap_lock = PTHREAD_MUTEX_INITIALIZER;
When you need to find a mutex, take the mutexMap_lock lock first. Once you have the mutex, drop the lock, and cache the mutex pointer so you don't have to keep referring to this mutexMap point of contention.