Different clients solve the problem in different ways, but generally one connection could only serve one thread if transactions are a requirement, unless special precautions are taken on the client sidea as threads would otherwise compete concurrently for the connection resource.
One option is to use locking (at the cost of performance, because other threads would have to wait until the transaction is complete).
Another option is to use connection pooling and use thread-per-connection patterns (this time at the cost of resources - as many active connections as there are active threads).
A third option is to do advanced multiplexing, such as with the StackExchange client for Redis (in this case at the cost of being able to do any of the blocking operations such as BLPOP / BRPOP / BRPOPLPUSH)
This topic is also highly dependent on how pipelining is achieved in the particular client and how data is processed.