0

Say we have std::map Sockets map, and it's a multithreaded application. There will be more than one threads accessing sockets in the map for sending socket data, meanwhile there will be only one thread accessing sockets in the map for receiving data and this thread will also delete the SocketInfo* if the remote end closes.

In the above situation, can we use the read-write lock (pthread_rwlock_t) to synchronize the threads? If yes, do we have more benefits than pthread_mutex_t?

Steve

[PSEUDO CODE]

     class CSocketIO {  
         std::map<int, SocketInfo*> m_Sockets; //socket value and socket info
         pthread_t  m_ReadingSocketThreads;   // for reading socket data
     };

     class CSession {
         void SendOutNetworkPackets(); //access sockets for sending sock data
         pthread_t m_WorkerThread;     // do jobs and send sock data
     };

     class CSomeClass {
         void SendOutNetworkPackets(); // also access sockets
         pthread_t m_WorkerThread;     // do jobs and send sock data
     };
Wallace
  • 561
  • 2
  • 21
  • 54

2 Answers2

0

Yes you can use a read/write lock to do this, its actually advisable to do so.

The benefit is that you can have multiple simultaneous readers with a read/write lock, whereas if you used a simple mutex, if one thread is reading, other threads that want to read would block, effectively serializing the reads. With a read/write lock, the readers will only block when a write is occurring.

Brady
  • 10,207
  • 2
  • 20
  • 59
0

You aren't allowing two threads to simultaneously write to the same socket, right? You just want to protect the lookup of a SocketInfo* from the map?

Reader-writer locks are rarely beneficial, and often harmful. When I have a client with a non-deterministic bug in a multithreaded program, the first culprit I look for is improperly used reader-writer locks. (You can only use reader locks to protect function calls that are truly const.)

Presumably each of your threads is doing something like this:

// do some work to figure out what to send
SocketInfo* my_socket_info = 0;

// critical section begins here
pthread_mutex_lock(the_map_mutex);
socket_map_t::const_iterator i = m_Sockets.find(id);
if (i != m_Sockets.end()) {
  my_socket_info = i->second;
}
pthread_mutex_unlock(the_map_mutex);
// critical section is done

if (my_socket_info != 0) {
  // do a bunch of work to actually send the data
  // (including acquiring a mutex specific to the socket unless
  // you have some other way of guaranteeing that the socket isn't
  // currently being written by some other thread)

The second question you need to ask (after "is what I'm protecting really const?") is: what percentage of the time is the_map_mutex locked? If it is less than about 50% then you don't have enough contention to make a reader-writer lock a win. You can get a good quick estimate of the utilization of the critical section protected by the_map_mutex by measuring the percentage of time a single thread spends inside the critical section and then multiplying by the number of hardware threads on your system.

Wandering Logic
  • 3,323
  • 1
  • 20
  • 25